Repository navigation
ADR 0098 G1: the RPC hang fault — a wedged op reaches terminal via op_deadline - #754
Merged
Merged
Conversation
…_deadline Closes coverage-gap G1 (#743, session 03e6535e): a resume-class op wedged forever inside its host RPC while the within-step heartbeat kept the op row fresh, so stale-op reclaim never fired — pinned 40 minutes until a pod roll. The op_deadline fix was deliberately built to be fired deterministically by the sim; this lands the fault that fires it. - SimHostState.rpc_hang: Option<Duration> replaces rpc_partitioned — a flag that was toggled by Step::RpcPartition and cleared in the heal block but NEVER READ anywhere (the "RPC partition" fault was inert; the real fail-fast path is up=false). Some(d): every SimHostClient verb sleeps d of virtual time at entry (lock released before the sleep). Above the verb's op_deadline this is the wedge — only the tokio-timer deadline drops the dispatch (auto-advance fires it deterministically on the paused clock); below it, a plain delay. Never future::pending() — an un-timed caller would deadlock the run-step-to-completion scheduler. - Step::RpcHang(host, bool) toggles it (3600s, far above every deadline), stays in the Chaos pick menu at the old partition weight, and is cleared in the quiescence-heal block. - Sim::execute is now pub so pinned scenarios can hand-drive exact interleavings (the engram-dst-host pattern); Step/DriverKind exported. - Pinned scenario wedged_boot_op_reaches_terminal_via_op_deadline: heartbeat-register -> Placed create -> hang both hosts -> the SessionOps driver's attempt returns ONLY because the deadline drops the hung verb (pre-#743 this step hangs the test forever), the op requeues (attempts advanced, never finished, never booted), and the healed quiescence pass converges it — no_op_dropped + quiescence-no-stragglers are the standing catch. - ADR: G1 marked CLOSED in §Coverage gaps. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What this is
Closes ADR 0098 §Coverage-gaps G1 (from #743 / session 03e6535e): a resume-class op wedged forever inside its host RPC while the within-step heartbeat kept the op row fresh — stale-op reclaim never fired, and the op pinned for 40 minutes until a pod roll. #743's
op_deadlinewas deliberately put on the tokio timer so the simulator's paused-clock advance could fire it deterministically; the seam was ready, the fault wasn't. This lands the fault.SimHostState.rpc_hang: Option<Duration>replacesrpc_partitioned— which turned out to be toggled byStep::RpcPartitionand healed in the quiesce block but never read anywhere (the "RPC partition" fault was inert; the real fail-fast path isup=false). Honest repurposing rather than a parallel knob.SimHostClientverb now callsmaybe_hang()at entry:Some(d)sleepsdof virtual time (lock released before the sleep). Above the verb'sop_deadlinethis is the Resume integrity: bound the stall, refuse the NBD corruption, show progress #743 wedge — only the tokio-timer deadline drops the dispatch; below it, a plain delay (the fault menu's "RPC delay" for free). Neverfuture::pending()— an un-timed caller would deadlock the run-step-to-completion scheduler.Step::RpcHang(host, bool)arms 3600s (far above every deadline), keeps the old partition weight in the Chaos menu, and is cleared in the quiescence-heal block.Sim::executeis nowpubso pinned scenarios can hand-drive exact interleavings (the engram-dst-host pattern);Step/DriverKindexported.wedged_boot_op_reaches_terminal_via_op_deadline: heartbeat-register → Placed create (only a Placed create enqueuescreate_boot— the first draft of this seed passed vacuously without the registration step, caught by strengthening the assertion) → hang both hosts → the SessionOps driver's attempt returns at all only because the deadline drops the hung verb (pre-Resume integrity: bound the stall, refuse the NBD corruption, show progress #743 the step hangs the test forever) → asserts the op was genuinely attempted-and-requeued (attempts ≥ 1, not finished, session not Active) → the healed quiescence pass converges it.no_op_dropped+quiescence-no-stragglersare the standing catch from here on.Verification
cargo nextest run -p engram-dst— 8/8 incl. the new seed and the existing pinned chaos seeds + replay determinism.cargo clippy -p engram-dst --all-targets -- -D warningsclean;cargo fmt --all --checkclean.Independent of #753 (P5) — disjoint crate closures; no merge-order constraint.
Per the standing P-series policy: leaving this open for your review — no admin-merge.
🤖 Generated with Claude Code