mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-07-18 03:31:02 +02:00
Fix MR-923: refresh restored coordinator on merge Err path
branch_merge_impl swaps the coordinator for the merge target, runs the merge body, then restores the original coordinator. A concurrent /change on the same target during this window publishes against the swapped coord, advancing on-disk manifest state that the restored coord doesn't see. The post-restore refresh was previously gated on merge_result.is_ok(), so the clean-409 path (merge body's post_queue_snapshot drift check returning a recoverable conflict) left the restored coord's cached snapshot stale relative to disk. The next sequential /change seeded its publisher expected_versions from that stale cache and 409'd with ExpectedVersionMismatch — a non-retryable conflict surfaced to a caller with no concurrent writer of their own. Refresh on both Ok and Err paths so cached state cannot diverge from the manifest across the swap-restore window. Add a focused regression test (concurrent_merge_clean_409_does_not_poison_next_change_on_target) that loops the cell-d scenario until the clean-409 branch fires and asserts the follow-up sentinel succeeds in that branch specifically. Co-Authored-By: Ragnor Comerford <ragnor.comerford@gmail.com>
This commit is contained in:
parent
19e9292ec0
commit
e91d5615c6
2 changed files with 99 additions and 1 deletions
|
|
@ -1109,7 +1109,22 @@ impl Omnigraph {
|
|||
.await;
|
||||
self.restore_coordinator(previous).await;
|
||||
|
||||
if merge_result.is_ok() && previous_branch == target_branch {
|
||||
// Refresh the restored coordinator on both Ok and Err paths.
|
||||
// During the swap window above, `self.coordinator` was a freshly
|
||||
// opened coord for the merge target; any concurrent writer on
|
||||
// that target (e.g. a `/change` on `main` racing a
|
||||
// `merge into=main`) publishes against the swapped coord and
|
||||
// never touches the original. Without this refresh, the
|
||||
// restored coord's cached manifest snapshot would diverge from
|
||||
// disk and seed a stale `expected_versions` into the next op's
|
||||
// publisher CAS fence — a non-retryable
|
||||
// `ExpectedVersionMismatch` for a user with no concurrent
|
||||
// writer of their own. Pinned by
|
||||
// `concurrent_merge_clean_409_does_not_poison_next_change_on_target`
|
||||
// in `crates/omnigraph-server/tests/server.rs` and by the
|
||||
// `[d:merge×change:into-target]` cell of
|
||||
// `concurrent_branch_ops_morphological_matrix`.
|
||||
if previous_branch == target_branch {
|
||||
self.refresh().await?;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue