Skip to content

feat: add opt-in WebSocket reconnect options - #23

Draft
chipkent wants to merge 1 commit into
fix/ws-keep-subscriptions-on-reconnectfrom
feat/ws-reconnect-options
Draft

chipkent wants to merge 1 commit into
fix/ws-keep-subscriptions-on-reconnectfrom
feat/ws-reconnect-options

Conversation

@chipkent

@chipkent chipkent commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Preview only. This is a draft in the fork showing the exact text of the PR planned for massive-com/client-python. It will be closed, not merged, once the upstream PR is opened.

Fixes #<issue: F2-options>

Builds on #19. Related to massive-com#818 and massive-com#935, which set today's reconnect behavior.

Defaults are unchanged. New WebSocketClient keyword arguments let a long-running client opt in:

Argument Default Effect
reconnect_backoff 0.0 Wait (s) before reconnecting after a connection closes; doubles per failure, with jitter of up to 20%
max_reconnect_backoff 120.0 Cap of that wait; at the cap, drawn from [cap / 1.2, cap] (never below reconnect_backoff)
reconnect_on_close False Reconnect when the server closes normally too
max_consecutive_failures None Raise after this many failures in a row
stable_uptime 60.0 Uptime (s) that resets the failure count and the backoff
raise_fatal_errors False Use websockets' default process_exception, which raises e.g. HTTP 404
WebSocketClient(reconnect_backoff=30, max_consecutive_failures=10)
  • A failure is a failed attempt, or a connection that closes within stable_uptime. max_reconnects keeps its meaning, and a close() while connected still ends connect(). A close() during the wait before a reconnect does not stop that reconnect; feat: add WebSocketClient.request_close() #24 makes it do so.
  • The constructor raises ValueError if reconnect_backoff is negative or greater than max_reconnect_backoff.
  • connect(process_exception=...) reaches websockets instead of raising TypeError.
  • New attribute max_connections_reached. The processor gets the same messages as before.
  • The loop is still async for ... in connect(...).

The knowledge base says the server takes "roughly 10 to 30 seconds" to release a dropped connection.

Tests

  • New test_reconnect_options.py patches random and asyncio.sleep instead of timing, and checks the ValueError. mock_server.py answers handshakes on /404/ with HTTP 404.
  • make test and make lint pass on 3.10 and 3.14.

@coderabbitai

coderabbitai Bot commented Oct 24, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

connect() reconnects at once after a dropped connection, returns when
the server closes the connection normally, retries a handshake error
such as HTTP 404 forever, and counts every disconnect over the client's
lifetime toward max_reconnects. A caller cannot change any of this.

Add keyword arguments to WebSocketClient. Each defaults to today's
behavior:

- reconnect_backoff, max_reconnect_backoff: wait before reconnecting
  after an open connection closes. The wait doubles with each failure
  in a row, up to the cap, plus up to 20% jitter; at the cap it is
  drawn from [cap / 1.2, cap], never below reconnect_backoff. The
  constructor raises ValueError if reconnect_backoff is negative or
  greater than max_reconnect_backoff.
- reconnect_on_close: also reconnect when the server closes normally.
  A close() by the caller while connected still ends connect().
- max_consecutive_failures, stable_uptime: limit failures in a row. A
  failure is an attempt that fails, or a connection that closes before
  it has been open for stable_uptime seconds. max_reconnects keeps its
  meaning.
- raise_fatal_errors: use websockets' default process_exception, which
  raises errors that retrying will not fix.

The reconnect loop is still async for ... in websockets' connect().
connect() now also accepts process_exception, which used to raise
TypeError because the client passed its own. The new attribute
max_connections_reached tells whether the server sent a
max_connections status during the last handshake; the processor
receives the same messages as before.
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