Commit 7ce038e
## TL;DR - the orphan race is already fixed; what was missing is a gate
that proves it
The brief asked for a `fix(core)` closing the #144 create-orphan race
behind the
`append-only-log` chaos flake. I reproduced the race, then established
that
**PR #146 (merged 2026-07-24) already closed it**. The stale piece was
the
scenario itself: it only hit the racy code path by luck, so it neither
caught
the bug reliably before the fix nor proves the fix now. This PR makes it
deterministic. **No core behaviour changes** - hence `test(chaos):`, not
`fix(core):`.
## What the race is
The first upload of `app.log` is a plain CREATE (no `drive_file_id`
yet). An
append that lands between the hash and the SPEC s8 post-upload `fstat`
makes
the executor settle it as changed-after-upload. Pre-#146 that left a
LIVE
object with no `file_state` row, adoptable only by the startup-gated
reconcile
pass, so the next mid-session scan planned a SECOND create. The
scenario's
"after reconcile, expected exactly 1 log object, found N" assertion is
exactly
that duplicate showing up.
Since #146 the executor instead commits a force-rescan `file_state` row
pointing at the just-created object and drops the op in one transaction
(`settle_post_upload_change` -> `commit_create_result`), so the next
scan
UPDATEs that object. One object, no restart needed.
## Evidence (M4 Mac, debug build, 4-6 way parallel, `driven-chaos
scenario run append-only-log`)
I gated the #146 settle behind a temporary env switch to get a true
negative
control, then removed it.
| build | injected remote delay | runs | pass | duplicate-object
failures |
|---|---|---|---|---|
| main (with #146) | none | 690 | 690 | **0** |
| main (with #146) | 3 ms | 240 | 240 | **0** |
| main (with #146) | 10 ms | 20 | 20 | **0** |
| #146 settle reverted | none | 200 | 194 | **6** (3.0%) |
| #146 settle reverted | 3 ms | 20 | 0 | **20** (100%, 2-14 objects
each) |
Two things fall out of that table:
1. The historical ~5-10% flake is reproduced at 3% on this host with the
fix
reverted, and is gone with the fix in - so the flake really was #144,
and
#146 really closed it.
2. Without an injected delay the scenario reaches the racy code path
only
occasionally. A green run therefore did **not** mean the create-orphan
path
was tested; it usually meant the window never opened. That is the actual
remaining defect.
## The change
- `AppendOnlyLog` now boots over
`InMemoryRemoteStore::with_slow_responses(3 ms)`
(`CREATE_RACE_DELAY`), deliberately under the 4 ms `MUTATE_EVERY`
mutation
cadence, so at least one append lands inside the create's upload window
on
every run. This is the same widening technique the `mid-upload-*` rows
already use with `SLOW_REMOTE`.
- Refreshed the two stale comment blocks that still described the
pre-#146
world ("leaves an orphan ... which is accepted behaviour"). The
reconcile +
drain step stays - it now stands in for the app restart that backstops
the
arms #146 deliberately left to reconcile (crash between upload and
settle,
versioned create, ambiguous `DeferToReconcile`) rather than papering
over a
routine duplicate.
Cost: +246 ms of wall clock per run of one scenario on the Windows CI
runner
(measured below).
## Verification on windows-latest (the platform the flake was reported
on)
The measurements above are from macOS, so here is the CI run of this
branch's
`chaos hermetic (windows-latest)` job:
- `append-only-log`: **pass**, `duration_ms: 523`. Baseline for the same
scenario on the same runner image, from an unmodified branch (#193's
run):
`duration_ms: 277`. So the real cost of forcing the window open is
**+246 ms**
on the 2-core Windows runner, not the ~150 ms I estimated from the Mac.
- Whole suite: **75 PASS / 10 SKIP / 0 FAIL / 0 FLAKY**, so widening
this row's
window does not destabilise the drain cap or any sibling row.
- `chaos fake-drive (windows-latest)` also green (this row is
hermetic-only, but
the sibling `mutator-fs-append-only-log` runs there: pass, unchanged).
## Verification on macOS
- `driven-chaos scenario run append-only-log` x **300 consecutive runs:
300 pass, 0 fail**
with this change applied.
- `driven-chaos run-all --hermetic`: 54 PASS / 31 SKIP / 0 FAIL / 0
FLAKY.
- `driven-chaos run-all --fault-injection`: 25 PASS / 2 SKIP / 0 FAIL /
0 FLAKY.
- `SQLX_OFFLINE=true cargo test --workspace`: green.
- `cargo clippy --workspace --all-targets -- -D warnings`: clean.
- `cargo fmt --all -- --check`: clean.
## Follow-up worth knowing
The `driven-append-only-log-chaos-flake` triage note ("re-run the Chaos
job, it
clears ~85-90% of the time") predates #146 and is now wrong: a
duplicate-object
failure on this row should be treated as a **real regression**, not a
re-run.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 19982cd commit 7ce038e
1 file changed
Lines changed: 58 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
103 | 111 | | |
104 | 112 | | |
105 | 113 | | |
| |||
959 | 967 | | |
960 | 968 | | |
961 | 969 | | |
962 | | - | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
963 | 1002 | | |
964 | 1003 | | |
965 | 1004 | | |
| |||
977 | 1016 | | |
978 | 1017 | | |
979 | 1018 | | |
980 | | - | |
981 | | - | |
982 | | - | |
983 | | - | |
984 | | - | |
985 | | - | |
986 | | - | |
987 | | - | |
988 | | - | |
989 | | - | |
990 | | - | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
991 | 1037 | | |
992 | 1038 | | |
993 | 1039 | | |
| |||
0 commit comments