fix(gateway): session recovery honors reset boundaries and real idle time (#68617 + #78618 salvage) - #82743
Merged
Merged
Conversation
Contributor
૮ >ﻌ< ა ci reviewran on 13fdecc — chore: map contributor email for hillimited all good! |
find_latest_gateway_session_for_peer filtered non-recoverable rows out of candidacy BEFORE ordering, so recovery could search behind a /new reset boundary and resurrect an older still-open row for the same peer — silently restoring the exact context the user reset. Rebuilt against the #82633 finder (has-messages ranking + COALESCE(last_activity_at, started_at) recency): the fence is expressed as a NOT EXISTS guard inside both the exact-key and peer-fallback queries — a candidate is rejected when an intentional boundary row (session_reset / session_switch / idle / daily / suspended / resume_pending_expired) for the same peer ended after the candidate's last activity. If the conversation's most recent event is an intentional reset, recovery returns nothing rather than reaching behind it. Cherry-picked from #68617 and adapted to the rewritten finder. (cherry picked from commit bb2c562)
Both session recovery paths (the startup stale-entry repoint and the lazy in-message recovery) rebuilt the routing entry with updated_at=now and never consulted _should_reset, so an opt-in idle/daily session_reset policy was silently dead across any gateway restart: a recovered session always looked freshly active, and since every subsequent message bumps updated_at, a session recovered stale could then never age out at all. Fix in three parts: - _create_entry_from_recovered_row derives updated_at from the durable last_activity_at the finder already returns on the row (no extra DB round-trip; the original PR added SessionDB.get_last_activity for this, unnecessary post-#82633), falling back to created_at. An invalid or missing started_at now maps to epoch 0 instead of now — an invalid durable timestamp must look old, never freshly active. reset_had_activity is set from the row's durable activity/message signals so the continuity hint stays accurate. - _recover_session_from_db evaluates _should_reset on the rebuilt entry: an overdue session is durably promoted to a reset boundary (promote_to_session_reset, falling back to end_session) and the stale mapping is dropped instead of repointed. - _query_recoverable_session no longer reopens the row; the get_or_create_session recovery phase evaluates _should_reset first and either feeds the normal auto-reset create path (reset notice, prev_session_id continuity, durable promotion) or reopens and publishes the recovered entry exactly as before. Behavior is unchanged under the default session_reset mode "none": _should_reset returns None there, so recovery still resumes every recoverable row — only users who opted into idle/daily resets see the policy actually applied across restarts. Cherry-picked from #78618 and adapted to the #82633 finder. (cherry picked from commit 31c71f7)
teknium1
force-pushed
the
salvage/reset-boundary-recovery
branch
from
August 9, 2026 21:58
ad8f24c to
13fdecc
Compare
This was referenced Aug 9, 2026
7 tasks
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.
Summary
Gateway session recovery now honors
/newreset boundaries and real idle time: a newer reset-ended row fences the finder from resurrecting older rows behind it, and recovered sessions keep their truelast_activity_atinstead of being stampedupdated_at=now(which made every recovered session look zero-seconds idle to reset policy).Combined salvage of #68617 (@Tranquil-Flow, Jul 21 — earliest submitter) and #78618 (@hillimited, Aug 4), cherry-picked with both authors preserved; the two PRs fix complementary halves of the same recovery flow and were composed onto #82633's rewritten finder.
Changes
hermes_state.py(find_latest_gateway_session_for_peer): NOT EXISTS fence on both the exact-key and peer-fallback queries — a candidate is rejected when a boundary row for the same peer (reset/switch/idle/daily/suspended/resume_pending_expired) ended more recently than the candidate's last activity (@Tranquil-Flow, intent re-expressed inside the rewritten query)gateway/session.py: recovered entries carry their realcreated_at/updated_atfrom the row (no morenowstamps), and both recovery paths consult reset policy before reopening (@hillimited; simplified to reuse thelast_activity_atthe finder already returns — the PR's separateget_last_activityDB method was unnecessary post-fix(gateway): make session identity durable so chat continuity survives crashes and restarts #82633)ORDER BY started_athunk and its "newer empty session hides history" test (both contradict Tracking: gateway session continuity breaks under state.db FTS corruption — orphan session fork + stale-session resume after restart #82616's deliberate has-messages ranking / empty-keyed-row semantics)Validation
Closes #68617 (credit @Tranquil-Flow) and #78618 (credit @hillimited). Part of #82616; also the surviving half of #71530's diagnosis (@FrendoWu).
Infographic