refactor(tui-gateway): _rebind_live_transport lives with the reattach contract in session_lifecycle
It is lifecycle logic (detached sentinel, reap cancel) and its siblings _reattach_refusal / _cancel_ws_orphan_reap are already there; server.py is the facade and gets no new definitions. Also trims the _claim_or_reuse_live comment to point at where the reap cancel now happens.
This commit is contained in:
@@ -2444,8 +2444,8 @@ def _claim_or_reuse_live(sid: str, session_key: str, record: dict, lease) -> tup
|
||||
if live is not None:
|
||||
if lease is not None:
|
||||
lease.release()
|
||||
# Guarded reuse cancels the reap only after accepting reattachment;
|
||||
# a rejected resume must leave an in-flight orphan interrupt polling.
|
||||
# The reap is cancelled by the guarded reuse (_reattach_refusal), not here: a rejected
|
||||
# reattach must leave an in-flight orphan interrupt polling.
|
||||
return live
|
||||
with _sessions_lock:
|
||||
_sessions[sid] = record
|
||||
@@ -2686,17 +2686,6 @@ def _live_visible_history(session: dict, db, in_memory_fallback: list[dict]) ->
|
||||
return in_memory_fallback
|
||||
|
||||
|
||||
def _rebind_live_transport(sid: str, session: dict, transport: Transport) -> None:
|
||||
"""Point a live session at ``transport`` (caller holds ``history_lock``)."""
|
||||
session["transport"] = transport
|
||||
# Every transport that showed this session (pop-outs resume the same sid); on disconnect the last
|
||||
# viewer becomes the transport instead of the drop sentinel.
|
||||
session.setdefault("viewers", {})[transport] = time.time()
|
||||
# See #83716.
|
||||
if transport is not _detached_ws_transport:
|
||||
_cancel_ws_orphan_reap(sid) # the client is back — a pending ws-orphan reap must not fire
|
||||
|
||||
|
||||
def _live_session_payload(
|
||||
sid: str, session: dict, *, cols: int | None = None, touch: bool = False,
|
||||
transport: Transport | None = None, omit_messages: bool = False) -> dict:
|
||||
|
||||
@@ -444,9 +444,9 @@ def _cancel_ws_orphan_reap(sid: str) -> None:
|
||||
|
||||
|
||||
def _reattach_refusal(rid, sid: str, session: dict) -> dict | None:
|
||||
"""Under ``_session_resume_lock``: the error a reattaching RPC (resume/activate/prompt.submit) must return
|
||||
instead of rebinding — ``session`` is no longer the live record for ``sid``, or a client-gone interrupt is
|
||||
still settling and the reap Timer must keep polling. None when the reattach may proceed."""
|
||||
"""Under ``_session_resume_lock``: why a reattaching RPC (resume/activate/prompt.submit) must NOT rebind
|
||||
``session`` — it is stale, or a client-gone interrupt is still settling and the reap Timer must keep
|
||||
polling. None when the reattach may proceed."""
|
||||
if _sessions.get(sid) is not session:
|
||||
return _err(rid, 4007, "session no longer live; retry resume")
|
||||
if session.get("_client_gone_interrupt_requested"):
|
||||
@@ -454,6 +454,17 @@ def _reattach_refusal(rid, sid: str, session: dict) -> dict | None:
|
||||
return None
|
||||
|
||||
|
||||
def _rebind_live_transport(sid: str, session: dict, transport: Transport) -> None:
|
||||
"""Point a live session at ``transport`` (caller holds ``history_lock``)."""
|
||||
session["transport"] = transport
|
||||
# Every transport that showed this session (pop-outs resume the same sid); on disconnect the last
|
||||
# viewer becomes the transport instead of the drop sentinel.
|
||||
session.setdefault("viewers", {})[transport] = time.time()
|
||||
# See #83716.
|
||||
if transport is not _detached_ws_transport:
|
||||
_cancel_ws_orphan_reap(sid) # the client is back — a pending ws-orphan reap must not fire
|
||||
|
||||
|
||||
def _ws_orphan_turn_activity_is_fresh(session: dict) -> bool:
|
||||
"""Whether a detached RUNNING turn's activity clock (``_touch_activity``) is still fresh — the reaper must NOT
|
||||
interrupt healthy detached work (closed laptop). Conservative: disabled threshold, missing/opaque agent, unreadable
|
||||
|
||||
Reference in New Issue
Block a user