Skip to content

fix(chat): apply every GetDelta batch, not only the first - #1976

Open
bmc08gt wants to merge 1 commit into
code/cashfrom
fix/chat-delta-sync-batches
Open

bmc08gt wants to merge 1 commit into
code/cashfrom
fix/chat-delta-sync-batches

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

GetDelta is a server stream (messaging_service.proto: rpc GetDelta(GetDeltaRequest) returns (stream GetDeltaResponse)), sending the catch-up as MessageBatches of at most 100 messages. Every response carries latest_sequence, the head as of stream open. performDeltaSync took .first(), wrote that batch, and set the cursor to the head. Anything past the first 100 messages was never fetched, and no later sync asked for it, because the cursor already claimed it.

Change

  • The stream is consumed to the end. Messages are buffered and written 500 at a time (DELTA_FLUSH_MESSAGES). Each write is followed by an applyCatchUp to the checkpoint_sequence of the last batch it holds, so a 1,000-message catch-up costs observers two invalidations rather than ten.
  • The cursor and sequenceTracker reach latest_sequence only when the stream completes.
  • A stream that fails, ends without a response, or runs past 60 s keeps what it delivered, and the next sync resumes from that checkpoint. The timeout is there because RealChatCoordinator runs the sync inline in its event handling, and a stream left open would hold every later event.
  • On RESET_REQUIRED after some batches, the delivered batches' checkpoint is kept, then LoadMessages runs as before. loadMessages only moves the cursor forward, so this marks rows that are stored.

Tests

DeltaSyncBatchesTest drives EventStreamDelegate with a multi-batch fake: three batches end at the head, a stream that drops after two resumes from batch two's checkpoint, a reset after one keeps it, and twelve batches are written in fewer than twelve transactions with the cursor only moving forward. The first three cases failed on code/cash; the twelve-batch case wrote 100 of 1,200 messages.

Numbers

The chat-load harness doesn't run performDeltaSync, and before this change the batches after the first were never applied, so there is no before/after to time.

GetDelta streams a catch-up as MessageBatch responses of at most 100
messages, and every response carries latest_sequence, the head as of
stream open. performDeltaSync took .first(), wrote that batch, then set
the cursor to the head. Anything past the first 100 messages was never
fetched, and no later sync asked for it, because the cursor already said
it was there.

The stream is now consumed to the end. Messages are written 500 at a
time (DELTA_FLUSH_MESSAGES), and each write moves the cursor to the
checkpoint_sequence of the last batch it holds. The cursor reaches the
head only when the stream completes. A stream that fails, ends early or
runs past 60 s keeps what it delivered, and the next sync resumes from
that checkpoint. The timeout exists because the coordinator runs the
sync inline in its event handling, and an open stream would hold it.

On RESET_REQUIRED after some batches, the delivered batches' checkpoint
is kept before LoadMessages runs. loadMessages only moves the cursor
forward, so this marks rows that are stored and nothing more.

DeltaSyncBatchesTest drives the delegate with a multi-batch fake. Its
first three cases failed before this change: a 12-batch catch-up wrote
100 of 1,200 messages.
@bmc08gt bmc08gt self-assigned this Nov 6, 2026
@github-actions github-actions Bot added the type: fix Bug fix label Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant