fix(#8): surface lease-release failure on forced exit and guard hydrate - #6
fix(#8): surface lease-release failure on forced exit and guard hydrate#6Jackallink wants to merge 1 commit into
Conversation
|
Independent review — 2026-09-04 Findings on PR #61. Hard-exit handler: releaseInFlightRuns may still be running after exitThe hardExit path now uses a Promise.race between releaseInFlightRuns and a 3s sleep. If releaseInFlightRuns takes longer than 3s, sleep resolves first, the race wins with sleep, and process.exit(0) runs. But releaseInFlightRuns is still in flight — it keeps running in the background until the process dies. The exit happens synchronously so the orphan promise is GC'd with the process; net effect is small but the in-flight call could have done partial writes. Same shape for the graceful-stop failure path. In practice, process.exit is the hammer, not a graceful cancel — this matches the function name stopWithBackstop. Acceptable. 2. Commit message clarityThe commit message says "surface lease-release failure on forced exit". The hardExit path's new exit code is 1 (was 0); the graceful-stop failure path's exit code was already 1 (was 1). Only the hardExit changes behavior. Suggest making that clearer in the PR body / commit message: only ONE of the two paths actually had its exit code changed. 3. configStore.hydrate siblingFiled as qm-integration#14. Same pattern, separate fix path. 4. AGENTS.md check
No blocking findings. The fix is correct. |
|
Deep-review pass addendum — 2026-09-04 Verified on branch
|
…guard hydrate src/wiring.ts stopWithBackstop hard-exit path used .finally(() => process.exit(0)). If releaseInFlightRuns rejected, the failure was logged implicitly and the exit was still 0, so containers/systemd saw a clean shutdown and never restarted. The graceful-stop failure path had the same issue at line 328. Also, void identity.hydrate() at line 460 dropped the derived promise, so a slow/dead identity store unhandled-rejected into a Node crash. Replace the hard-exit .finally with a .then(onResolve, onReject) that exits 1 on rejection after logging errMessage(e); the graceful-stop failure path now .catch()es then .finally()es exit(1). Add .catch(() => undefined) to identity.hydrate so a dead identity backend cannot crash the boot. configStore. hydrate at line 491 is the same pattern and filed as Jackallink/qm-integration#14. Refs: Jackallink/qm-integration#8
f695e8a to
792a9ad
Compare
|
Amended — 2026-09-04 (addresses deep-review F6.3, partially)
|
Closes: Jackallink/qm-integration#8
src/wiring.tsstopWithBackstophard-exit path used.finally(() => process.exit(0)). If releaseInFlightRuns rejected, the failure was logged implicitly and the exit was still 0, so containers/systemd saw a clean shutdown and never restarted. The graceful-stop failure path had the same issue at line 328. Also,void identity.hydrate()at line 460 dropped the derived promise, so a slow/dead identity store unhandled-rejected into a Node crash.Replace the hard-exit .finally with a .then(onResolve, onReject) that exits 1 on rejection after logging errMessage(e); the graceful-stop failure path now .catch()es then .finally()es exit(1). Add .catch(() => undefined) to identity.hydrate so a dead identity backend cannot crash the boot. configStore.hydrate at line 491 is the same pattern and filed as Jackallink/qm-integration#14.
Affected tests
Reviewer checklist