Skip to content

Feat/socket backoff jitter#226

Merged
Osuochasam merged 6 commits into
Open-audit-foundation:mainfrom
benedictworks-home:feat/socket-backoff-jitter
Jun 25, 2026
Merged

Feat/socket backoff jitter#226
Osuochasam merged 6 commits into
Open-audit-foundation:mainfrom
benedictworks-home:feat/socket-backoff-jitter

Conversation

@benedictworks-home

Copy link
Copy Markdown
Contributor

Summary
Replaces the bare onclose null-assignment in useLiveFeed.ts with a structured reconnection loop using exponential backoff and full jitter. Previously, a dropped connection simply cleared the socket ref with no retry logic at all. Under sustained outages, clients would silently stay disconnected. With this change, they automatically recover while protecting the server from reconnection storms.

What changed
useLiveFeed.ts

Added three tunable constants: BACKOFF_BASE_MS (1 s), BACKOFF_MULTIPLIER (2×), BACKOFF_MAX_MS (30 s)
Added computeBackoffDelay(attempt) — applies the exponential curve, caps it at 30 s, then randomises the result across [0, cappedDelay] (full jitter pattern)
attemptRef tracks the current retry count and resets to 0 on ws.onopen after a successful handshake
reconnectTimerRef holds the pending setTimeout handle so it can be cancelled immediately when the user manually stops the feed — no leaked timers, no duplicate sockets
isLiveRef mirrors the isLive state flag so the onclose closure can safely read the current intent without going stale
closeSocket() strips the onclose handler before calling .close() so intentional disconnects never trigger a retry cycle
Unmount cleanup sets isLiveRef.current = false before calling disconnect(), ensuring any in-flight timer is a no-op if it fires after the component is gone
Backoff behaviour
Attempt Capped delay Actual delay (full jitter)
0 1 s 0 – 1 s
1 2 s 0 – 2 s
2 4 s 0 – 4 s
3 8 s 0 – 8 s
4 16 s 0 – 16 s
5+ 30 s (cap) 0 – 30 s
Full jitter ensures that a fleet of simultaneously-disconnected clients spreads reconnection attempts uniformly across the interval rather than spiking at the same moment (thundering herd mitigation).

Verification
tsc --noEmit — zero errors in useLiveFeed.ts
eslint lib/hooks/useLiveFeed.ts --max-warnings=0 — passed clean
Only
useLiveFeed.ts
staged; no unrelated files touched
Files changed
lib/hooks/useLiveFeed.ts | 1 file, +123 / -11

Closes #86

- Add @types/js-yaml as a devDependency with flexible version constraint
- Change from pinned version 4.0.9 (which has Windows-only OS restriction) to ^4.0
- This allows npm to select a compatible version without platform restrictions
- Fixes Docker build failure on Linux where npm ci was failing with:
  'Unsupported platform for @types/js-yaml@4.0.9: wanted {"os":"win32"}'

Resolves build failure on job 83241645142
@benedictworks-home benedictworks-home force-pushed the feat/socket-backoff-jitter branch from f42b5d0 to 7fcb7e2 Compare June 25, 2026 10:32
@Osuochasam Osuochasam merged commit 8a3820b into Open-audit-foundation:main Jun 25, 2026
5 of 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.

[Backend] Robust WebSocket Reconnection Strategy with Exponential Backoff

2 participants