fix(core-backend): control randomness to fix flaky test #6936
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.
Explanation
Current State
The
BackendWebSocketServicetests were experiencing flakiness after introducing the new ExponentialBackoff logic using Cockatiel. The random jitter in the exponential backoff algorithm was causing non-deterministic test behavior, particularly in tests that relied on precise timing control withjest.advanceTimersByTime().Symptoms:
Solution
This PR fixes all flaky tests by making the exponential backoff behavior deterministic and adjusting test timing to prevent race conditions.
1. Added
Math.random()Mock to 9 TestsMocked
Math.random()to return0in tests that involve reconnection logic. This ensures Cockatiel's exponential backoff delays are predictable and consistent across test runs:should handle abnormal WebSocket close by triggering reconnectionshould reset reconnect attempts after stable connectionshould skip connect when reconnect timer is already scheduledshould handle WebSocket onclose during connection phaseshould clear connection timeout in handleClose when timeout occurs then close firesshould not schedule multiple reconnects when scheduleReconnect called multiple timesshould force reconnection and schedule connectshould skip forceReconnection when reconnect timer is already scheduledshould stop reconnection when isEnabled returns false during scheduled reconnect2. Timing Adjustments to Prevent Race Conditions
Changed
completeAsyncOperations(10)tocompleteAsyncOperations(0)in 6 tests to check state immediately after operations without allowing timers to execute prematurely:should handle WebSocket onclose during connection phase- After simulateCloseshould clear connection timeout in handleClose when timeout occurs then close fires- After manual close triggershould not schedule multiple reconnects when scheduleReconnect called multiple times- After both close eventsshould force reconnection and schedule connect- After forceReconnection callshould skip forceReconnection when reconnect timer is already scheduled- After simulateErrorshould skip connect when reconnect timer is already scheduled- After simulateClose3. Coverage Stability
Fixed intermittent coverage issues for:
connect()when reconnect timer is already scheduledforceReconnection()when reconnect timer is already scheduledThese lines are now consistently covered by ensuring reconnect timers remain scheduled during assertions.
Technical Details
Exponential Backoff with Jitter:
Math.random()to add jitter to prevent thundering herd problemsMath.random() = 0, delays are deterministic and tests can advance time preciselyTiming Philosophy:
completeAsyncOperations(0): Flush promises only, no time advancementTesting
Verified stability with extensive testing:
References
Checklist
Note
Stabilizes BackendWebSocketService reconnection tests by mocking Math.random jitter and using immediate async flushing to avoid timer races, with minor state/idempotency assertions added.
packages/core-backend/src/BackendWebSocketService.test.ts)Math.random()to0in reconnection-related tests to make Cockatiel backoff jitter deterministic.completeAsyncOperations(10)withcompleteAsyncOperations(0)where assertions must occur before timers run (e.g., aftersimulateClose/simulateError, post-forceReconnection).CONNECTINGstate during connection-phase close handling.scheduleReconnectcalls).Written by Cursor Bugbot for commit 6333eda. This will update automatically on new commits. Configure here.