Skip to content

fix(lib): reconnect when the first WebSocket attempt is refused - #2216

Merged
joepio merged 1 commit into
developfrom
claude/upload-roundtrip-socket
Oct 11, 2026
Merged

joepio merged 1 commit into
developfrom
claude/upload-roundtrip-socket

Conversation

@joepio

@joepio joepio commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Before: in Node, a Store whose first WebSocket attempt was refused (server not listening yet, or a busy runner) stayed offline forever. It logged "[WS] Connection failed" once and never tried again. This is the dead socket behind the upload-roundtrip reds in develop runs 5208 and 5211, which stop the lib integration stage and hide every e2e result.

After: the client retries on the normal backoff and connects as soon as the server answers.

Node's WebSocket (undici) fires only error on a refused connection, never close. The client scheduled its retry, and rejected openPromise, on close alone.

How: teardown and retry move into one end() per socket, run at most once, called from close and from error when the socket never opened. openPromise rejects from there too. Browsers, which do fire close after error, behave as before.

Test: tests/ws-reconnect.integration.test.ts points a Store at a port that refuses, then puts the real server behind that port. It is red without the fix ("expected false to be true") and green with it. Lib unit tests (1550) and all lib integration tests pass locally, including upload-roundtrip.


Generated by Claude Code

Node's WebSocket (undici) fires only 'error' on a refused connection,
never 'close'. The client scheduled its retry and rejected openPromise
on 'close' alone, so a Store whose first attempt came before the server
listened stayed offline for good. This is the dead socket in develop
runs 5208 and 5211, where upload-roundtrip logged '[WS] Connection
failed' and then waited out its timeout.

Teardown and retry now run once per socket from 'close', and from
'error' when the socket never opened.
@joepio
joepio merged commit 416c79b into develop Oct 11, 2026
8 checks passed
@joepio
joepio deleted the claude/upload-roundtrip-socket branch October 11, 2026 12:13

joepio commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Complexity review after merge (+130/-49 in websockets.ts plus a 67-line integration test). Fine as is.

The per-socket end() replaces the retry code that lived only in close, reuses _retryTimer/_retryDelay, and has no module-level state, so nothing is duplicated. Two optional notes: the error and close handlers still both call abort/reportConnected(false) for an opened socket (harmless, slightly redundant, websockets.ts ~526-545), and the doubling backoff is written separately in browser-peer-sync.ts (retryDelays); a shared helper is only worth it if a third copy appears. The test uses a real 1.5 s delay plus polling up to 20 s, so watch it for flakiness.


Generated by Claude Code

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.

1 participant