π DB-owned message sequences β fix broken conversation ordering#32
Merged
π DB-owned message sequences β fix broken conversation ordering#32
Conversation
Sequences were computed by app code in 4 places (Claude connector, Codex connector, transition.rs, SessionHandle), each with different strategies. This caused 82/86 messages to have sequence=0 in one dogfooding session, breaking pagination entirely. Fix: DB computes sequences via MAX(sequence)+1 on INSERT. App-layer code no longer assigns sequences β entries arrive with sequence=0 and the DB assigns the authoritative value. RowUpsert preserves the original sequence on conflict (no overwrite). - Remove msg_counter and fetch_add from Claude connector - Remove sequence assignment in transition RowCreated handler - Update SQL for RowAppend/RowUpsert to use DB-computed sequences - Add V029 migration to fix historical broken sequences via rowid
The previous commit made the DB compute sequences, but broadcasts still used in-memory sequences. If a DB write failed silently, the two could diverge. Now broadcasts wait for the DB-assigned sequence before emitting to clients. One source of truth, zero divergence. - Add oneshot response channel to RowAppend/RowUpsert persist commands - execute_command reads back DB-assigned sequence and sends via channel - Writer flushes immediately when any command has a response channel - AddRowAndBroadcast/UpsertRowAndBroadcast await DB sequence before broadcast - dispatch_transition_input uses 3-pass: persist β await sequences β broadcast - Add set_row_sequence() and row_by_id() to SessionHandle - Remove Clone from PersistCommand (was unused, blocked oneshot::Sender) - Rewrite actor tests with mock writer that simulates DB sequence assignment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MAX(sequence)+1β app code never assigns sequences.msg_counter/fetch_addremoved from Claude connector, conditional assignment removed from transition.rs.sequence=0) usingROW_NUMBER() OVER (PARTITION BY session_id ORDER BY rowid).Why
Dogfooding revealed Codex direct sessions were missing user messages. Root cause: sequences were computed independently in 4 places (Claude connector, Codex connector, transition.rs, SessionHandle). Any restart, restore, or path disagreement could corrupt ordering permanently. Now there's one code path and one source of truth.
How it works
sequence: 0RowAppend/RowUpsertpersist command includesoneshot::Sender<u64>COALESCE(MAX(sequence)+1, 0)on INSERTexecute_commandreads back assigned sequence and sends via oneshotKey files
persistence/mod.rspersistence/commands.rssequence_txon RowAppend/RowUpsert, removed Clonepersistence/writer.rssession_command_handler.rsconnector-claude/src/lib.rsconnector-core/src/transition.rssession.rsset_row_sequence(),row_by_id()session_actor.rsV029__fix_message_sequences.sqlTest plan
make rust-ciβ fmt + clippy + 437 tests passSELECT sequence FROM messagesincrements