Skip to content

fix(live): recover the shared WebSocket from silent half-open connections #117

Description

@dborup

Problem

At fork audit ref 1bdf088e, public/app.js::connectWS() reconnects only from onclose. A proxy/NAT drop, sleep/resume, or stuck handshake can leave the browser-side socket apparently open but silent, so all views sharing it stop receiving live updates indefinitely. The server sends protocol-level WebSocket pings every 30 seconds in cmd/server/websocket.go, but browser JavaScript cannot observe those frames.

Upstream reference: Kpa-clawbot/CoreScope#2020. This needs an adapted port, not a blind cherry-pick.

Acceptance criteria

  • The server emits a small application-level heartbeat from its existing single WebSocket writer loop, without adding a competing writer or changing dead-client handling.
  • The client tracks liveness from socket creation; any received frame refreshes it. A socket or handshake silent beyond a documented threshold is replaced exactly once.
  • onclose, the watchdog, online, visible-tab resume, and pull-to-reconnect cannot stack reconnect timers or leave multiple live sockets.
  • Old handlers are detached before intentional replacement.
  • Heartbeats are consumed before logo pulses, cache invalidation, pause buffers, or onWS listeners. Normal packet messages remain unchanged.
  • Preserve the configured reconnect delay for ordinary close events and document old-tab behavior during a rolling static-asset update.

Tests

  • Deterministic fake-clock/fake-WebSocket tests for a silent OPEN socket, never-open handshake, traffic/heartbeat refresh, clock steps, online/visibility resume, ordinary close, and repeated/pull reconnect races.
  • Go tests for the heartbeat cadence and the existing protocol ping behavior.
  • Register tests locally and in CI without changing workflow triggers, permissions, or fork guards.

Non-goals

No deploy, publish, release, or staging/production contact. Do not broaden this into unrelated WebSocket UI work.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions