Skip to content

refactor: Socket Unification — a fixed 2-WebSocket budget per tab (state socket + relay mux)#378

Merged
sahil-noon merged 4 commits into
mainfrom
sockets-v2
Jul 17, 2026
Merged

refactor: Socket Unification — a fixed 2-WebSocket budget per tab (state socket + relay mux)#378
sahil-noon merged 4 commits into
mainfrom
sockets-v2

Conversation

@sahil-noon

Copy link
Copy Markdown
Collaborator

Summary

Session-state SSE streams saturate the browser's 6-per-origin HTTP/1.1 pool on plaintext origins — and on Firefox/WebKit a full pool blocks new WebSocket handshakes entirely, so a multi-server host could never connect a terminal. This branch collapses the per-tab connection budget from panes + servers + 1 long-lived streams to exactly two WebSockets: /ws/state (all session-state + host-metrics) and /ws/terminals (all pane relays, muxed). Evidence: docs/findings/socket-pool-accounting.md, docs/findings/relay-mux-hol.md; design: fab/plans/sahil/socket-unification.md.

Changes

  • State socket (refactor: State Socket — mux session-state + host-metrics SSE into one WebSocket #375, change 260716-qf3j-state-socket): new /ws/state handler with an in-band hello/subscribe/ack protocol; sseHub client edge generalized to per-connection subscription sets (producers frozen, payloads byte-identical); GET /api/sessions/stream + handleSSE retired; session-context.tsx swapped onto a StateSocket client preserving every attachServer/subscribe* seam; connection dots keyed on subscription acks; 12 e2e specs migrated to a shared /ws/state mock; structurally fixes the long-standing attachServer→SSE race (multi-server-sidebar flake).
  • Relay mux (refactor: Relay Mux — one terminal WebSocket per tab #377, change 260717-803u-relay-mux): new /ws/terminals handler — binary [u32 streamId][payload] frames + JSON control ops, per-stream bounded queues + fair scheduler (spike-proven v1 requirement: 1.66s → 32ms echo p50 under co-stream flood); handleRelay + /relay/{windowId} retired; frontend RelayMux singleton + TerminalClient port preserving the four delicate seams (confirmation-gate receipt, connect-select epoch, pane suspension as stream close/open, per-stream deferred reset); connection-budget e2e guard tightened to 2 WS + 0 SSE.
  • Post-review cleanup sweep (ecd5eeeb): dead BoardEntriesFetcher chain and dead setPreviewScope client fn removed; dead /relay Vite dev-proxy block dropped; relay.go folded into the socket files (shared upgraderstate_ws.go, forceTERMterminals_ws.go); test-only outFrame.payload() relocated to the test file; unused e2e mock control surface collapsed; stale SSE/EventSource transport comments reworded across backend + frontend.

Chat still rides its own SSE by design — it joins the state socket in change 3 (chat-on-state-socket), not in this branch.

sahil-noon and others added 4 commits July 17, 2026 11:22
…e WebSocket (#375)

* refactor: Mux session-state + host-metrics SSE into one WebSocket

Replace the per-server EventSource pool and host-metrics EventSource with
a single /ws/state connection (hello/subscribe/ack protocol), eliminating
steady-state h1 pool usage that was blocking WebSocket handshakes on
Firefox/WebKit once 6 SSE connections saturated the pool. Retires
GET /api/sessions/stream; SSE event names/payloads move verbatim into the
new envelope, and attachServer/subscribe* consumer seams are unchanged.

* Update ship status and record PR URL

* fix: address review feedback from @Copilot

* Update review-pr status

---------

Co-authored-by: Sahil Ahuja <sahilahuja@gmail.com>
# Conflicts:
#	app/frontend/tests/e2e/chat-view.spec.ts
#	docs/memory/run-kit/index.md
#	docs/memory/run-kit/ui-patterns.md
Co-authored-by: Sahil Ahuja <sahilahuja@gmail.com>
@sahil-noon
sahil-noon marked this pull request as ready for review July 17, 2026 18:57
@sahil-noon
sahil-noon merged commit c9702b3 into main Jul 17, 2026
5 checks passed
@sahil-noon
sahil-noon deleted the sockets-v2 branch July 17, 2026 18:57
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