feat(streaming): add jittered exponential backoff and online/offline awareness to ledger stream reconnects - #815
Open
zainabwahab-eth wants to merge 3 commits into
Conversation
…o ledger stream reconnects - Add exponential backoff WITH jitter to reconnect logic in StreamManager._scheduleReconnect() - Uses baseDelay * 2^attempt with full jitter (random [0, baseDelay)) scaled by RECONNECT_JITTER_FACTOR - Caps maximum delay at RECONNECT_MAX_DELAY_MS (30s) to prevent unbounded growth - Jitter factor controls jitter range: factor=1 gives full [0, baseDelay), factor=0 gives deterministic backoff - Add online/offline browser awareness - Listen for window online/offline events via _registerOnlineListeners() - _setIsOnline() pauses reconnection when offline (cancels timer, does NOT increment attempts) - When coming back online, resets reconnect attempts to 0 and starts from base delay - Status transitions to 'reconnecting' while paused offline for caller awareness - Graceful degradation in unsupported environments - Defaults _isOnline to true when navigator is unavailable (SSR, node tests) - _registerOnlineListeners() is no-op without window - _setIsOnline() degrades gracefully without throwing - Add JSDoc documentation for all constants explaining strategy, parameters, offline-pause behavior, and compatibility notes - Cap backoff at 30s max delay so retries don't grow indefinitely Co-authored-by: system Closes Nanle-code#748
…awareness to ledger stream reconnects - Add exponential backoff with full jitter (baseDelay * 2^attempt, random [0, baseDelay)) - Cap maximum backoff delay at 30s (RECONNECT_MAX_DELAY_MS) - Add max reconnect attempts limit (10) - Implement online/offline awareness using navigator.onLine and window online/offline events - Pause reconnection attempts entirely while browser is offline (don't burn retry attempts) - Reset backoff and resume reconnection immediately when coming back online - Gracefully degrade in SSR/test environments without navigator/window - Add comprehensive tests for jitter, backoff cap, online/offline pause, and edge cases - Update package.json to fix duplicate dependency entries Closes Nanle-code#748
|
@zainabwahab-eth is attempting to deploy a commit to the nanle-code's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@zainabwahab-eth Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Collaborator
|
@zainabwahab-eth Please fix all the CI checks failure! |
_setIsOnline(true) reset backoff and flipped status to 'connecting' but never called _openStream(), so a stream paused offline never actually resumed once connectivity returned. Also replaces the reconnect test suite's tautological assertions (reimplemented formulas, bare expect(true).toBe(true) placeholders) with tests that mock the Horizon server and drive the real StreamManager through connect/error/offline paths under fake timers. Co-Authored-By: Claude Sonnet 5 <[email protected]>
Author
Done. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #748
Summary
This PR implements jittered exponential backoff and online/offline awareness for the ledger stream reconnection logic in src/lib/streaming.js.
Changes
Validation
Update: additional validation and a bug fix found during rigorous testing
While re-validating against a byte-for-byte baseline comparison against upstream/master, found and fixed a real bug, and strengthened the test suite:
Bug fix: _setIsOnline(true) reset the backoff counter and flipped status to 'connecting' but never actually called _openStream() — meaning a stream paused while offline would never resume on reconnection, it would just sit reporting "connecting" forever. Fixed in streaming.js.
Test suite rewrite: the original 10 tests mostly reimplemented the backoff/jitter formula inline and asserted against that reimplementation rather than the real code, and two ended in bare expect(true).toBe(true). Rewrote as 7 tests that mock the Horizon server and drive the actual StreamManager under fake timers — all pass, all exercise real code paths:
Primary flow: connects, emits incoming ledgers to subscribers, resets backoff on message
Boundary (max attempts): stops scheduling further reconnects once MAX_RECONNECT_ATTEMPTS is reached
Boundary (delay ceiling): caps delay at RECONNECT_MAX_DELAY_MS, applies jitter so repeated failures don't retry at a fixed interval
Failure (stream error): schedules a reconnect delay in [0, baseDelay) capped at the max, then reopens the stream
Failure (offline): pauses reconnection without incrementing attempts while offline, resumes immediately with backoff reset when connectivity returns (this test verifies the bug fix above)
Pre-existing issues, unrelated to this change
Baseline measured against a clean upstream/master checkout (via a separate git worktree, so the working branch was undisturbed):
npx tsc --noEmit: 1431 pre-existing errors. This branch has the exact same 1431 (byte-identical diff of sorted error lists) — zero new type errors introduced.
npm run lint: 1546 pre-existing problems (51 errors, 1495 warnings). This branch has the identical 1546/51/1495 — zero new lint issues, and none of the pre-existing ones touch streaming.js or streaming.test.ts.
Note on package.json fix: upstream/master's package.json is itself invalid JSON as committed (a duplicate docs:validate-drift script key with a missing comma) — npm run lint/npm install fail outright on a clean checkout with EJSONPARSE. The fix mentioned above removes only that duplicate key — no dependency/version changes; package-lock.json is untouched and identical to upstream.
Vite's "chunks larger than 500 kB" build warning is a pre-existing bundle-size characteristic of the repo, unrelated to this change.