feat: implement offline request queue for WebSocket resilience#151
feat: implement offline request queue for WebSocket resilience#151sarthakNITT wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds an “offline replay” mechanism so requests issued during reconnect can be queued, preserved across disconnects, and resent once the WebSocket is connected again.
Changes:
- Introduces an
offlineQueueto store serialized requests while disconnected/reconnecting. - Pauses request timeouts on reconnectable disconnects and restarts them when replaying queued requests.
- Flushes queued requests on successful reconnect (
connectedstate).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/ios-client.ts | Adds offline queue + timeout pause/replay logic for the iOS client WebSocket requests. |
| src/instance-client.ts | Adds the same offline queue + timeout pause/replay approach for the TS instance client. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 71920f3. Configure here.
| clearTimeout(request.timeout); | ||
| request.reject(new Error('Connection closed during request')); | ||
| pendingRequests.delete(id); | ||
| } |
There was a problem hiding this comment.
Replayed requests dropped second disconnect
Medium Severity
After flushOfflineQueue replays queued work, entries leave offlineQueue while still in pendingRequests. On a later reconnectable disconnect, the close handler only keeps requests whose ids remain in offlineQueue, so replayed-but-unanswered requests are rejected with Connection closed during request instead of being held for another replay.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 71920f3. Configure here.
There was a problem hiding this comment.
Intentional. If a request is actively in-flight over the wire when the socket drops, it is unsafe to automatically replay it as it could cause duplicate non-idempotent operations.


This PR fixes a major resilience issue where a temporary network disconnect would immediately drop and reject all pending WebSocket requests.
Introduced an offline request queue to hold requests during temporary disconnects and replay them once the connection is re-established. This guarantees zero dropped requests during network blips without blocking the main thread or forcing consumers to write their own retry wrappers.
Changes Made -
src/ios-client.ts & src/instance-client.ts:
Verification -
Tested that yarn build succeeds with no type errors.
Tested that yarn test passes completely.
Verified yarn fix formatting matches the repo standard.
closes #150
Note
Medium Risk
This changes when promises resolve or reject across disconnects and could replay commands the server already handled; Android asset installs remain fail-fast on disconnect.
Overview
WebSocket clients in
instance-client.tsandios-client.tsno longer reject every pending command as soon as the socket drops. They now buffer outbound commands while the link isconnectingorreconnecting, then replay them afteropenviaflushOfflineQueue, with per-request timeouts restarted at send time.sendRequestaccepts work when the socket is not open but a reconnect is in progress (instead of failing immediately). On an unexpected close that will retry, in-flight requests are rejected withConnection closed during request, while queued entries stay inpendingRequestsfor replay; AndroidsendAssetin-flight work is still rejected and is not offline-queued. Hitting max reconnect attempts now runsfailPendingRequests, which also clears the offline queue.Reviewed by Cursor Bugbot for commit 71920f3. Bugbot is set up for automated code reviews on this repo. Configure here.