Skip to content

refactor: extract endSession teardown helper - #134

Merged
dolonet merged 3 commits into
dolonet:mainfrom
gorevds:refactor/end-session-helper
Jun 26, 2026
Merged

dolonet merged 3 commits into
dolonet:mainfrom
gorevds:refactor/end-session-helper

Conversation

@gorevds

@gorevds gorevds commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

What

Five sites hand-rolled the same transport teardown (closeStream, stopKeepalive, polling=false, sid=null, plus assorted extras): the session-error auto-reconnect, auth_failed, alive===false, the transport-gave-up fallback, and the vault no-key disconnect. This folds the core into endSession(p, o) with the genuinely-different bits opt-in:

  • o.disconnect — POST /api/disconnect for the pre-null sid (fire-and-forget)
  • o.save — saveSessions()
  • o.badge — updatePaneBadge(p)

The deferred-save timer is now cleared and nulled at every site, not just the vault one (clearing drops the closure's pane ref; nulling makes p.saveCommitTimer truthiness meaningful).

Two behavior fixes the extraction surfaced (adversarial review)

  1. connectPane success now re-arms scheduleSaveCommit when a pendingSave is outstanding. The auto-reconnect path silently relied on the OLD deferred-save timer firing against the reassigned sid to commit the save on an idle SSE session. Clearing the timer in endSession exposed that — and reconnects outside the 2.6s window had always lost the idle-save (pre-existing gap, also fixed by the re-arm). New test pins the scenario and was verified to fail without the re-arm.
  2. transportFatal bails when p.polling is already false. A stale long-poll rejection / SSE error from a transport that endSession already tore down must not re-banner the pane — and must not reset p.connecting, which would defuse connectPane's in-flight duplicate guard during an auto-reconnect (double /api/connect + leaked server PTY).

Ordering preserved

Per-site operation order verified against pre-image (badge-before-bar, save-after-bar, banner-before-teardown); the auth_failed badge/recentOutput swap is unobservable (badge reads neither). Sites that legitimately pair closeStream/stopKeepalive for transport restarts (visibility resume, SSE→long-poll fallback) are deliberately untouched.

Tests

626 frontend tests OK (+1 new: pendingSave survives a session-error auto-reconnect; verified red without the fix).

gorevds and others added 3 commits June 12, 2026 18:56
Five sites hand-rolled the same transport teardown (closeStream,
stopKeepalive, polling=false, sid=null, plus assorted extras): the
session-error auto-reconnect, auth_failed, alive===false, the
transport-gave-up fallback, and the vault no-key disconnect. Fold the
core into endSession(p, o) with the genuinely-different bits opt-in
(o.disconnect / o.save / o.badge). The deferred-save timer is now
cleared (and nulled) at every site, not just the vault one.

Two fixes that review of the extraction surfaced:

- connectPane's success path re-arms scheduleSaveCommit when a
  pendingSave is still outstanding. Before, the auto-reconnect path
  relied on the OLD timer firing against the reassigned sid to commit
  the save on an idle SSE session; clearing the timer in endSession
  exposed that, and reconnects outside the 2.6s window had always
  lost the idle-save. New test pins the scenario (fails without the
  re-arm).
- transportFatal now bails when p.polling is already false: a stale
  long-poll rejection / SSE error from a transport endSession tore
  down must not re-banner the pane or reset p.connecting (which would
  defuse connectPane's in-flight duplicate guard mid-reconnect).

626 frontend tests OK.
@dolonet
dolonet merged commit b19be2f into dolonet:main Jun 26, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants