Giter VIP home page Giter VIP logo

Comments (16)

ochan12 avatar ochan12 commented on May 17, 2024 1

Hi, @amyblais I was able to reproduce it in the community server by doing.
(I tested it with messages between two different accounts)

  1. Start a reply to a message and then change the focus out from the reply, creating a draft.
  2. Delete the first message. (Now if I go to the deleted message it appears as (message deleted) and on the drafts tab it still shows)
  3. If I now close the app on the account writing the draft reply and reopen it, the (message deleted) disappears from the channel but the badge in the Drafts tab still shows a number, but no draft

from mattermost.

marianunez avatar marianunez commented on May 17, 2024 1

@ochan12 after the root post is deleted and does the Draft count update properly after you click away from the Draft section to somewhere else?

Nevermind @ochan12, we were able to reproduce on our side. Thanks for reporting this. Will open this issue for Up for Grabs for community support

from mattermost.

devinbinnie avatar devinbinnie commented on May 17, 2024 1

@Utsav-Ladani

So the problem with 1) is that we can't guarantee that a draft was stored on the server in the first place, and this means that we could lose locally-stored drafts from when the app was disconnected.

What would 2) involve? I know we have the channelId and threadId which should be enough to define uniqueness.

from mattermost.

Utsav-Ladani avatar Utsav-Ladani commented on May 17, 2024 1

Hello @devinbinnie

I created a draft PR and left a comment to resolve. Can you please help me resolve it?

from mattermost.

Utsav-Ladani avatar Utsav-Ladani commented on May 17, 2024 1

Thank you all 🎉

from mattermost.

marcin-kwiatkowski avatar marcin-kwiatkowski commented on May 17, 2024 1

Thank you for response 💪🤝

from mattermost.

amyblais avatar amyblais commented on May 17, 2024

Hi @ochan12, I wasn't able to reproduce this just now. Are you able to reproduce this on our community server https://community.mattermost.com/, which is on the latest version?

from mattermost.

ochan12 avatar ochan12 commented on May 17, 2024

image

from mattermost.

amyblais avatar amyblais commented on May 17, 2024

Opened https://mattermost.atlassian.net/browse/MM-55613.

from mattermost.

marianunez avatar marianunez commented on May 17, 2024

@ochan12 after the root post is deleted and does the Draft count update properly after you click away from the Draft section to somewhere else?

from mattermost.

Utsav-Ladani avatar Utsav-Ladani commented on May 17, 2024

Hello @marianunez @amyblais, I would like to grab this.

I explored the code and found that when a user deletes a post two delete requests are sent to the server, one for the post itself and one for draft. The server only deletes the draft of the sender, but other users' drafts will stay in the db like an orphan draft without root_id. That's why we are seeing draft counts more than it should be.

I also noticed that even if we somehow manage to delete those records from DB, we still have more draft count. It is because we store the draft in the IndexDB of the browser using the localforage package and it is not getting flushed properly when a post is deleted by the user who posted it. Even page refresh will not work.

Possible Solution

  • We have to delete drafts of all users that are associated with a post. It should be done on the server side because of security (The user might delete other users' drafts without deleting his/her post if we do it from the client side).
  • We also have to remove the drafts that are no longer valid ( root post is deleted )

Let me know your suggestions and insights. 💡

Thanks

from mattermost.

marianunez avatar marianunez commented on May 17, 2024

Thanks for looking into this issue @Utsav-Ladani!

@devinbinnie any thoughts on the approach above?

from mattermost.

devinbinnie avatar devinbinnie commented on May 17, 2024

Thanks for looking into this issue @Utsav-Ladani!

@devinbinnie any thoughts on the approach above?

Seems good to me.

from mattermost.

Utsav-Ladani avatar Utsav-Ladani commented on May 17, 2024

Hello @devinbinnie!

I've successfully identified and resolved an issue, implementing the fix as outlined above. My solution involves removing drafts from the server upon deletion of the root post. However, there's a hiccup with locally stored data.

In the proposed fix, when a user deletes a post, all associated draft comments are promptly deleted on the server side. Subsequently, the user receives the POST_DELETED event, triggering a setGlobalItem function. This function removes data from IndexedDB, resulting in the update of our Draft count and drafts list.

The challenge arises when a user is offline, preventing the reception of the POST_DELETED event. Consequently, locally stored data persists indefinitely.

Upon the initialization of the React App, it utilizes Redux persist storage and a reducer to fetch comment drafts from the server, merging them with the local state stored in IndexedDB using the localForage package.

For a detailed look, refer to:

/**
* Gets drafts stored on the server and reconciles them with any locally stored drafts.
* @param teamId Only drafts for the given teamId will be fetched.
*/
export function getDrafts(teamId: string) {
const getLocalDrafts = makeGetDrafts(false);
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
const state = getState() as GlobalState;
let serverDrafts: Draft[] = [];
try {
serverDrafts = (await Client4.getUserDrafts(teamId)).map((draft) => transformServerDraft(draft));
} catch (error) {
return {data: false, error};
}
const localDrafts = getLocalDrafts(state);
const drafts = [...serverDrafts, ...localDrafts];
// Reconcile drafts and only keep the latest version of a draft.
const draftsMap = new Map(drafts.map((draft) => [draft.key, draft]));
drafts.forEach((draft) => {
const currentDraft = draftsMap.get(draft.key);
if (currentDraft && draft.timestamp > currentDraft.timestamp) {
draftsMap.set(draft.key, draft);
}
});
const actions = Array.from(draftsMap).map(([key, draft]) => {
return setGlobalItem(key, draft.value);
});
dispatch(batchActions(actions));
return {data: true};
};
}

This code snippet reveals that the getDrafts function fetches data from the server and merges it with locally stored drafts. In our case, the draft persists locally even after post deletion when the user is offline.

The crux of the issue lies in how the server and locally stored drafts are merged. The provided code demonstrates that the merging step only adds new drafts to the store without removing others. This assumption is based on the belief that other drafts are from different teams.

Considering that drafts are fetched every time, the question arises: why do we need to store them in local storage within the merged map?

My proposed solution:

  1. Remove the merge step as it is unnecessary AFAIK
  2. Use a different method and a data format to store and update the map. e.g. we can add the teamIdproperty to map value object

Please help me to choose the best solution

Thanks

from mattermost.

marcin-kwiatkowski avatar marcin-kwiatkowski commented on May 17, 2024

Is it really resolved? I am experiencing right now the same issue.

  • MacOS 14.2.1, M1
  • Client: 5.6.0
  • Server: 9.4.2
  • Self-hosted MM instance.
Screenshot 2024-02-09 at 15 51 27

Steps that were done:

  1. Person A wrote a message.
  2. Person A deleted a message.
  3. Person B saw the deleted message as (message deleted) in main window.
  4. Person B opened thread window and wrote any letter. Draft has been saved.
  5. Person B refreshed the window (cmd+R). The result can be seen on the screen below.

from mattermost.

marianunez avatar marianunez commented on May 17, 2024

@marcin-kwiatkowski the fix for this one should land in v9.6 server so seems to be expected to be still an issue in your server that is 9.4.2

from mattermost.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.