Advance persists its own catalog when no working catalog is given - #2436
Conversation
The head confirm inside CompareAndAdvanceBranch reopens the store when a peer changed it, and that reload can replace the live session catalog with the peer's freshly written working set. Persisting the working set from the live session after that bound the peer's content to the newly advanced head, so the staleness gate accepted it: a fast-forward merge racing a concurrent commit could publish a working set missing the merged rows, and the peer's next commit made the loss permanent. Advancing with no explicit working catalog means the working set is the new catalog itself; persist that. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
SummaryCoverage spans core repository setup and data durability, including branch creation and advancement, merges, rebases, cherry-picks, reopening, and preservation of working state. It also exercises adversarial concurrency, lock contention, conflicting operations, retries, and injected persistence failures, with healthy behavior across both normal and failure-recovery paths. Safe to merge — the run found no regressions or PR-attributable failures, and the exercised persistence, branching, conflict handling, concurrency, and recovery behaviors remained consistent. No merge blocker is indicated. Tests run by Ito
Tip Reply with @itoqa to send us feedback on this test run. |
DoltLite performance vs PR base
blobpk details
compositepk details
int details
textpk details
vc details
All relative performance gates passed. |
DoltLite source coverage
Merged 200 pooled raw profiles from the distributed Linux correctness jobs. Per-file coverage (97 files)
|

Fixes #2433.
Root cause — captured live with instrumented CI soaks
The nightly's
merge_race_feat_rows_presentflake is silent data loss in a fast-forward merge racing a concurrent commit, cross-process:RefreshAndConfirmHeadsees the store changed and reloads the live session from disk, silently replacing the merge content with the writer's working set.PersistWorkingSetWithHash(NULL)flushes the clobbered live session: the writer's stale content gets bound to the new head. The staleness gate accepts it.The instrumented capture shows the poisoned write directly:
[ws] br=main cat=2ae6 commit=a9b6— writer content, feat-head binding — followed by the writer's[cmt] expected=a9b6 cat=2ae6advancing over it. The preserved store hasfeat workin main's ancestry with zero feat rows.Fix
AdvanceBranchWithStatewith no explicit working catalog now persists the catalog being advanced to instead of the reload-vulnerable live session — advancing with no working catalog means the working set is the new catalog. Covers FF, the merge-commit path, cherry-pick, and rebase finalize. One caller depended on the old live-flush: seed-init keeps a user's pre-seed tables in the working set, and now passes the flushed live catalog explicitly.Verification
soak/mp-merge-race-2433(never to merge; I'll delete it after this lands). The nightly stress soak remains the ongoing sentinel — the race needs hundreds of Linux runs to fire, so no deterministic CI test can gate it.🤖 Generated with Claude Code