Repository navigation
fix(#1462): a stranded Compiling claim is re-driven by the sweep that already runs - #1593
Conversation
… already runs `Compiling` is a non-terminal state and nothing reconciles it. The flip to `Compiling` is DURABLE; the terminal write is not guaranteed — a process death mid-compile leaves the row there for good. DynamicTypePreWarmer's "don't clobber an in-flight compile someone else already started" guard then declines to touch it on EVERY subsequent sweep, so the type never reaches a terminal state. It is neither Ok (usable) nor Error (classifiable by #1396's discriminator), it holds portal readiness, and it parks every instance hub for the full activation budget. One row on public.mesh_nodes sat at `Compiling` for ten weeks this way — harmless only because it was an orphan the prewarmer never enumerates. Apply the same mechanism to a row that IS in the bake set and it is the readiness-refusal shape #1391 opened with. The guard now defers only to a claim that can still be in flight: * Pending — always honoured. It is the state this prewarmer itself writes to ASK for a compile; re-driving it would fight our own request. * Compiling — honoured only while LastCompileStartedAt is within the per-type budget, the same bound the sweep gives a type to settle. Past it no driver is still working on it: it either finished (and would have written a terminal state) or it died. * Compiling with NO start timestamp — stranded. A live compile always stamps one, so an unstamped Compiling is exactly the shape a row left over from an older write carries, and honouring it forever is how this became permanent. 🚨 What this is NOT: no timer, no poller, no background sweep for stale rows — the issue rules those out explicitly and so does AGENTS.md. The recovery rides the enumeration that ALREADY runs, and only ever reinterprets a claim that has provably expired. StrandedCompileClaimTest pins that distinction, which is the whole substance of the change. Verified: MeshWeaver.Hosting.Test 176/176 (8 new); MeshWeaver.Hosting and MeshWeaver.Hosting.Test build -c Release -warnaserror with 0 errors, 0 warnings. Fixes #1462 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmBFaHTqhy7h742wkAaJKj
There was a problem hiding this comment.
Pull request overview
This PR addresses issue #1462 where a NodeType can remain stuck in the non-terminal Compiling state indefinitely (e.g., after a mid-compile process crash), causing subsequent prewarm sweeps to permanently defer and never re-drive the type to a terminal status.
Changes:
- Refines
DynamicTypePreWarmer’s “don’t clobber an in-flight compile” guard to only defer to compile claims that can still be live (freshCompilingwithin the existing per-type budget, orPending). - Introduces
IsLiveCompileClaim(...)to centralize and test the stranded-claim interpretation. - Adds
StrandedCompileClaimTestto pin the intended behavior for fresh vs. stale/unstampedCompilingclaims.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/MeshWeaver.Hosting/DynamicTypePreWarmer.cs | Updates the sweep’s guard to re-drive stranded Compiling claims via IsLiveCompileClaim, preventing permanent non-terminal status. |
| test/MeshWeaver.Hosting.Test/StrandedCompileClaimTest.cs | Adds unit coverage for the new “live vs stranded compile claim” logic. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Review comment checked and not applied —
Restored, and Resolving the thread. |
Compilingis a non-terminal state that nothing reconciles. The flip to it is durable; the terminal write is not guaranteed — a process death mid-compile leaves the row there for good.DynamicTypePreWarmer's "don't clobber an in-flight compile someone else already started" guard then declines to touch it on every subsequent sweep:So the type never reaches a terminal state. It is neither
Ok(usable) norError(classifiable by #1396's discriminator), it holds portal readiness, and it parks every instance hub for the full activation budget. The row that revealed this sat atCompilingfor ten weeks — harmless only because it was an orphan the prewarmer never enumerates. Apply the same mechanism to a row that is in the bake set and it is the readiness-refusal shape #1391 opened with.The fix
The guard now defers only to a claim that can still be in flight:
PendingCompiling, started within the per-type budgetCompiling, started longer ago than the budgetCompiling, no start timestampThe bound is the sweep's own per-type budget, not a new number.
🚨 What this is not
No timer, no poller, no background sweep for stale rows. The issue rules those out explicitly ("Do not add a timer that polls for stale
Compilingrows and flips them — that is the watchdog-shaped band-aid AGENTS.md rules out"), and so does AGENTS.md.The recovery rides the enumeration that already runs, and only ever reinterprets a claim that has provably expired.
StrandedCompileClaimTestpins exactly that distinction — including the case that must NOT change (a compile 5 s old is still honoured), because a fix here that clobbered live compiles would be worse than the bug.Verification
MeshWeaver.Hosting.Test— 176/176, 8 of them new.-c Release -warnaserror—MeshWeaver.Hosting,MeshWeaver.Hosting.Test: 0 errors, 0 warnings.No What's New entry: the user-visible effect (a portal that will not become ready) is a failure that this prevents rather than a change they can notice.
Fixes #1462
🤖 Generated with Claude Code
https://claude.ai/code/session_01KmBFaHTqhy7h742wkAaJKj