fix(gateway): prevent restart resume fan-out after clean drain - #69697
fix(gateway): prevent restart resume fan-out after clean drain#69697pvspencer22 wants to merge 3 commits into
Conversation
Related: #11099 also moves clean-shutdown marking earlier, but this PR uses a broader exact-marker and clean-drain-consumption policy to distinguish interrupted work from idle-session fan-out. These are related mechanisms, not a duplicate. |
15e4af7 to
766b013
Compare
|
Thanks for the careful lifecycle work. The current-main premise is verified: Problems
Suggested changes
Automated hermes-sweeper review. |
766b013 to
bdb9343
Compare
|
Addressed in the latest head ( |
bdb9343 to
2ca153f
Compare
2ca153f to
ede5e08
Compare
Summary
restart_timeoutorshutdown_timeout, including older exact markers whose adapter was unavailable during an intervening clean processrestart_interruptedrecovery until genuine inbound user activity instead of emitting startup turnsProblem
A gateway could drain conversational work successfully and then be terminated during slower teardown before writing
.clean_shutdown. The next startup treated the missing marker as evidence of a crash, heuristically marked recently active but idle sessions asrestart_interrupted, and injected blank synthetic startup turns across unrelated topics.Two adjacent lifecycle races mattered as well:
Recovery policy
A known drain timeout identifies actual interrupted work and can justify intentional continuation. A generic crash heuristic cannot prove that a user turn was interrupted, so it preserves the session for the next real inbound message without automatically emitting user-visible startup output.
Clean proof applies only to the immediate predecessor's heuristic crash classification. It does not blanket-suppress older exact timeout evidence. Shutdown reservation and recovery-state persistence are serialized per session so successful completion and interruption marking have a defined order.
The marker remains one-shot. A later clean drain replaces any stale invalidation tombstone, and chats that finish during the drain window have their pre-drain recovery markers cleared even if only cron or API work remains at timeout.
Testing
Fresh verification on the exact refreshed head:
.venv/bin/python -m py_compile gateway/run.py gateway/session_state.py tests/gateway/test_clean_shutdown_marker.py tests/gateway/test_restart_resume_pending.py.venv/bin/ruff check gateway/run.py gateway/session_state.py tests/gateway/test_clean_shutdown_marker.py tests/gateway/test_restart_resume_pending.pygit diff --check upstream/main...HEADThe focused cluster includes deterministic regressions for startup failure after lock ownership, post-rename marker inspection failure, fail-closed marker invalidation, mixed clean proof plus older exact recovery, failed pre-drain marking followed by successful completion, delayed successful-turn clear versus newer shutdown marking, generic-crash fan-out suppression, drain completion cleanup, and one-shot marker invalidation.
Platform notes
Validated on Linux. Marker timing and startup recovery classification are supervisor-independent and do not introduce platform-specific APIs.
AI Assistance
The implementation, regression tests, and analysis were prepared with AI agents.
Related to #25966