feat(gateway): add crash checkpoint for precise session recovery - #8143
feat(gateway): add crash checkpoint for precise session recovery#8143chinadbo wants to merge 3 commits into
Conversation
|
This would solve session crash issues, please merge! |
9aa85f3 to
63d5af7
Compare
Persist in-flight agent runs to agent_checkpoints.json so that on restart the gateway can precisely identify interrupted sessions instead of relying solely on the suspend_recently_active time-window heuristic. Sessions found in the checkpoint are suspended and the checkpoint is cleared; the time-window heuristic remains as fallback.
- Fix startup ImportError: replace non-existent HERMES_HOME import with module-level _hermes_home variable (gateway was failing to start) - Gate mark_completed on generation ownership: stale runs no longer clear the checkpoint entry when a newer generation owns the slot - Add fsync + unique mkstemp to _write: checkpoint is now durable across power failures and safe under concurrent gateway instances - Add defensive mark_completed on /stop sentinel fast-path for future-proofing if mark_running timing ever shifts
- Clear checkpoint on clean shutdown to prevent stale entries accumulating - Add mark_completed after stale-eviction and interrupt-clear paths - Move tempfile import to module level
19fa0c0 to
cfb0764
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for pursuing a real crash-recovery gap: current main still uses the 120-second updated_at sweep in gateway/session.py:2053-2087.
Problems
- The checkpoint does not make recovery precise yet.
gateway/run.py:2261-2269reads and processes checkpoint entries, butgateway/run.py:2273-2275immediately runssuspend_recently_active()for every recently updated session, retaining the false positives the checkpoint is intended to avoid. - The PR calls
suspend_session()atgateway/run.py:2264. On current main, that is the hard auto-reset path (gateway/session.py:1932-1945); interruption continuity instead usesmark_resume_pending()(gateway/session.py:1947-1974) to preserve the transcript and session ID. tests/gateway/test_session_crash_recovery.py:104-120tests the checkpoint class alone, not gateway startup or the fallback interaction.
Suggested changes
- Treat a valid checkpoint as authoritative and use the timestamp sweep only when no checkpoint is available.
- Adapt recovery to current
resume_pendingsemantics and add a runner-level test covering a checkpointed in-flight session plus a recently completed session.
Automated hermes-sweeper review.
|
|
||
| # Fallback: time-window heuristic for sessions not tracked by checkpoint. | ||
| try: | ||
| suspended = self.session_store.suspend_recently_active() |
There was a problem hiding this comment.
This fallback still sweeps every recently updated session even when a checkpoint was present, so it reintroduces the false positives the checkpoint is meant to eliminate. Use the heuristic only when no valid checkpoint is available, or explicitly exclude the authoritative checkpoint recovery path.
| interrupted = self._crash_checkpoint.get_active_sessions() | ||
| if interrupted: | ||
| for session_key in interrupted: | ||
| self.session_store.suspend_session(session_key) |
There was a problem hiding this comment.
On current main, suspend_session() is the hard auto-reset path. Crash continuity now uses mark_resume_pending() so the existing session ID and transcript survive; salvage should target that contract rather than reset the recovered session.
Summary
SessionCrashCheckpointclass that persists in-flight agent runs toagent_checkpoints.jsonsuspend_recently_active()time-window heuristic remains as fallback for sessions not tracked by the checkpointTest plan
tests/gateway/test_session_crash_recovery.py