fix(gateway): allow ws_orphan_reap rows in session recovery (#63207)

Whitelist ws_orphan_reap alongside agent_close in
find_latest_gateway_session_for_peer so gateway stale-routing
self-heal can reopen wrongly-reaped messaging sessions instead of
minting empty replacements. Layer A prevention already landed in #60609.
This commit is contained in:
HexLab98 2026-07-12 21:29:55 +07:00 committed by kshitij
parent 71e91f89b5
commit ca907480ae
2 changed files with 10 additions and 8 deletions

View file

@ -1904,9 +1904,10 @@ class SessionStore:
# Stale routing self-heal (#54878): the in-memory entry
# points at a session that has ALREADY been ended in
# state.db. Drop it and fall through to recovery/create.
# Recovery finder reopens ``agent_close`` rows (preserving
# the transcript) but returns None for other end_reasons
# (e.g. /new), starting a fresh session.
# Recovery finder reopens ``agent_close`` and mistaken
# ``ws_orphan_reap`` rows (preserving the transcript) but
# returns None for other end_reasons (e.g. /new), starting
# a fresh session.
logger.warning(
"gateway.session: routing key %r -> %s is ended in "
"state.db but still live in sessions.json; dropping "

View file

@ -2113,9 +2113,10 @@ class SessionDB:
pruned after process-level restart bugs. New gateway sessions persist
the deterministic ``session_key`` on the durable session row so the
mapping can be rebuilt exactly. Rows ended only by older gateway
cleanup's ``agent_close`` bug are treated as recoverable; explicit
conversation boundaries such as /new, /resume switches, and compression
splits are not.
cleanup's ``agent_close`` bug or a mistaken TUI ``ws_orphan_reap``
(dashboard viewer disconnect before #60609) are treated as recoverable;
explicit conversation boundaries such as /new, /resume switches, and
compression splits are not.
"""
if not session_key:
return None
@ -2125,7 +2126,7 @@ class SessionDB:
SELECT * FROM sessions
WHERE session_key = ?
AND source = ?
AND (ended_at IS NULL OR end_reason = 'agent_close')
AND (ended_at IS NULL OR end_reason IN ('agent_close', 'ws_orphan_reap'))
AND (COALESCE(message_count, 0) > 0 OR EXISTS (
SELECT 1 FROM messages WHERE messages.session_id = sessions.id LIMIT 1
))
@ -2150,7 +2151,7 @@ class SessionDB:
AND COALESCE(chat_id, '') = COALESCE(?, '')
AND COALESCE(chat_type, '') = COALESCE(?, '')
AND COALESCE(thread_id, '') = COALESCE(?, '')
AND (ended_at IS NULL OR end_reason = 'agent_close')
AND (ended_at IS NULL OR end_reason IN ('agent_close', 'ws_orphan_reap'))
AND (COALESCE(message_count, 0) > 0 OR EXISTS (
SELECT 1 FROM messages WHERE messages.session_id = sessions.id LIMIT 1
))