Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix duplicating messages and improve performance #10058

Merged
merged 2 commits into from
Jul 28, 2023

Conversation

ShGKme
Copy link
Contributor

@ShGKme ShGKme commented Jul 26, 2023

☑️ Resolves

Steps to reproduce:

  1. Open ChatA
  2. Switch to ChatB
  3. From another tab or user send a message to ChatA
  4. Wait until LeftSidebar will be updated
  5. Return back to ChatA
  6. You can see duplicate messages 😣

Why it happens:

  1. In the messagesStore we update conversation.lastMessage in the conversation store using a new received message in the chat. Here a reference is passed to the conversationsStore's action

    if (conversation && conversation.lastMessage && lastMessage.id > conversation.lastMessage.id) {
    context.dispatch('updateConversationLastMessage', {
    token,
    lastMessage,
    })

  2. In the conversationsStore then this reference is saved in the store:

updateConversationLastMessage(state, { token, lastMessage }) {
Vue.set(state.conversations[token], 'lastMessage', lastMessage)
},

  1. At this step conversationsState.conversation[token].lastMessage stores a reference to a message object from messagesStore

  2. Then we patch conversationsState.conversation[token].lastMessage after receiveing new conversation on re-fetching. This mutates the object in the messages store.

patchConversation(state, conversation) {
patchObject(state.conversations[conversation.token], conversation)
},

Another problem:

There is also conversation.lastMessage.messageParameters array. patchObject is not patching sub-arrays, so it caused almost unnecessary re-renders anyway.

🖼️ Screenshots

Green highlight = re-rendering. After PR there are more re-renderings in changed conversation items, but no re-renderings in not changed items.

🏚️ Before 🏡 After
image image
before-rerender after-rerender

🚧 Tasks

  • Instead of patching conversation - re-assign it when the new conversation has larger lastActivity
    • Drawbacks:
      • It assumes that lastActivity is enough to know if there were any changes in the conversation
      • It could be a little bit less optimal than patching

👀 Alternatives

  1. Clone lastMessage on update from messagesStore
  • But there is a patching error anyway. So
    1. Adjust patchObject to handle arrays (check length and elements)
    • But it seemed to be too overkill to me
  1. Adjust patchObject to handle "special" cases and list custom setters for specific keys (lastMessage)
    • But it seemed to be too overkill to me
  2. Store lastMessageId instead of lastMessage in the conversation, same as lastCommonReadMessage
    • I'd like this solution, but it would require many changes. The best alternative solution for me

🏁 Checklist

patchConversation(state, conversation) {
patchObject(state.conversations[conversation.token], conversation)
updateConversationIfHasActivity(state, conversation) {
if (state.conversations[conversation.token].lastActivity < conversation.lastActivity) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to do it when the unread counter changes, because reading a chat does not update the lastactivity

@ShGKme
Copy link
Contributor Author

ShGKme commented Jul 27, 2023

@nickvergessen do you think the change in the last commit is too much and should be replaced with just direct 'unreadMessages', 'unreadMention', 'unreadMentionDirect' checks?

Or it is fine and better to have this large update "just in case" and checks?

@ShGKme ShGKme force-pushed the fix/10027/duplication-messages branch 4 times, most recently from d8b77e4 to 60e9aef Compare July 27, 2023 11:36
@ShGKme
Copy link
Contributor Author

ShGKme commented Jul 27, 2023

@nickvergessen @Antreesy If this is fine for you, I'll add some tests and ready to merge

Copy link
Contributor

@Antreesy Antreesy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing blocking from me.
Tested with replies, works properly now

@@ -209,7 +251,9 @@ const actions = {
* @param {object} conversation the conversation;
*/
addConversation(context, conversation) {
context.dispatch('emitUserStatusUpdatedWhenChanged', conversation)
if (conversation.type === CONVERSATION.TYPE.ONE_TO_ONE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (conversation.type === CONVERSATION.TYPE.ONE_TO_ONE) {
if (conversation.status) {

Group conversations don't have a status field, so I'm not sure if we needed that additional check before and need that now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nickvergessen Do you remember if there was a reason to add this check here: #9411

Except readability

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be that the user has no status now, but had one before. Then the event should trigger and delete the status.
Can e.g. happen when they go invisible, or when the inactive status gets purged.

That being said, it doesn't make sense with the rest of the code, so I guess no.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But not sure it's legal to trigger the event with "undefined"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we never have this request without includeStatus, I added emit for null status as emitting about status removal.

src/store/conversationsStore.js Outdated Show resolved Hide resolved
src/store/conversationsStore.js Outdated Show resolved Hide resolved
@ShGKme
Copy link
Contributor Author

ShGKme commented Jul 27, 2023

Updated user status update emitting.

Added test for all these cases around conversations updating and user status update emitting.

@ShGKme ShGKme marked this pull request as ready for review July 27, 2023 20:40
@Antreesy Antreesy self-requested a review July 28, 2023 08:38
Copy link
Contributor

@Antreesy Antreesy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦭

Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
@ShGKme ShGKme force-pushed the fix/10027/duplication-messages branch from 03723ab to 74320c9 Compare July 28, 2023 08:41
@ShGKme
Copy link
Contributor Author

ShGKme commented Jul 28, 2023

Rebased onto master and squashed

@ShGKme ShGKme enabled auto-merge July 28, 2023 08:41
@ShGKme ShGKme merged commit 36f53c1 into master Jul 28, 2023
18 checks passed
@ShGKme ShGKme deleted the fix/10027/duplication-messages branch July 28, 2023 08:57
@ShGKme
Copy link
Contributor Author

ShGKme commented Jul 28, 2023

/backport to stable27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[Bug] Dissapearing messages / duplicated messages in chat
3 participants