Skip to content

msglist: Suppress duplicate message on fetch/event race - #2388

Open
chrisbobbe wants to merge 1 commit into
zulip:mainfrom
chrisbobbe:claude/issue-929-review-d3memg
Open

msglist: Suppress duplicate message on fetch/event race#2388
chrisbobbe wants to merge 1 commit into
zulip:mainfrom
chrisbobbe:claude/issue-929-review-d3memg

Conversation

@chrisbobbe

Copy link
Copy Markdown
Collaborator

Fixes #929.

When the user navigates to a narrow, the message fetch can race with the event queue: a newly sent message appears in the fetch response and then later arrives as a message event. Before now, the message would get shown twice in the message list; this commit fixes that.

On handling a message event, when the message is already in the list, skip adding a duplicate. Do adopt the event's copy of the message, though, because the message store has done the same, and the list's messages should remain identical to the store's so that the message reflects subsequent update events.

Do this adoption before the narrow/haveNewest checks that gate adding a new message. Those checks answer whether a new message belongs in the list; but a message we already have must stay in sync with the store regardless -- including in a search narrow (where containsMessage is null) or when the list hasn't yet reached the newest message.

@chrisbobbe chrisbobbe added the maintainer review PR ready for review by Zulip maintainers label Jul 24, 2026

@rajveermalviya rajveermalviya left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @chrisbobbe! All LGTM, with couple nits below, otherwise please feel free to merge.

Comment thread lib/model/message_list.dart Outdated
Comment on lines +1160 to +1161
messages[index] = message;
contents[index] = parseMessageContent(message);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: Do we want to pull this into a helper on _MessageSequence, something like _replaceMessage(int index, Message message)? Because it seems direct writes to messages and contents is exposed only by it's helpers.

Comment thread lib/model/message_list.dart Outdated
Comment on lines +1162 to +1169
if (event.localMessageId != null) {
// We sent this message; drop its outbox counterpart.
// (When [haveNewest] is false there are no [outboxMessages], so this
// is a no-op; see [_syncOutboxMessagesFromStore].)
final localMessageId = int.parse(event.localMessageId!, radix: 10);
outboxMessages.removeWhere(
(message) => message.localMessageId == localMessageId);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: This is identical to code below at line 1201, do we want to move this into a helper?

Fixes zulip#929.

When the user navigates to a narrow, the message fetch can race with
the event queue: a newly sent message appears in the fetch response
and then later arrives as a message event. Before now, the message
would get shown twice in the message list; this commit fixes that.

On handling a message event, when the message is already in the list,
skip adding a duplicate.  Do adopt the event's copy of the message,
though, because the message store has done the same, and the list's
messages should remain identical to the store's so that the message
reflects subsequent update events.

Do this adoption before the narrow/haveNewest checks that gate adding
a *new* message.  Those checks answer whether a new message belongs in
the list; but a message we already have must stay in sync with the
store regardless -- including in a search narrow (where containsMessage
is null) or when the list hasn't yet reached the newest message.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chrisbobbe
chrisbobbe force-pushed the claude/issue-929-review-d3memg branch from c80552b to c450ada Compare July 28, 2026 18:18
@chrisbobbe

Copy link
Copy Markdown
Collaborator Author

Oh wow, my Claude session (Claude Code on the Web, see #2379) did that force-push all by itself—I haven't reviewed its work yet; I'll need to do that.

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

Labels

maintainer review PR ready for review by Zulip maintainers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prevent duplicate message on fetch/event race

2 participants