Skip to content

feat: implement offline request queue for WebSocket resilience#151

Open
sarthakNITT wants to merge 2 commits into
limrun-inc:mainfrom
sarthakNITT:queueBranch
Open

feat: implement offline request queue for WebSocket resilience#151
sarthakNITT wants to merge 2 commits into
limrun-inc:mainfrom
sarthakNITT:queueBranch

Conversation

@sarthakNITT

@sarthakNITT sarthakNITT commented Jun 13, 2026

Copy link
Copy Markdown

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.ts and ios-client.ts no longer reject every pending command as soon as the socket drops. They now buffer outbound commands while the link is connecting or reconnecting, then replay them after open via flushOfflineQueue, with per-request timeouts restarted at send time.

sendRequest accepts 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 with Connection closed during request, while queued entries stay in pendingRequests for replay; Android sendAsset in-flight work is still rejected and is not offline-queued. Hitting max reconnect attempts now runs failPendingRequests, 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.

Copilot AI review requested due to automatic review settings June 13, 2026 08:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 offlineQueue to 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 (connected state).

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.

Comment thread src/ios-client.ts Outdated
Comment thread src/ios-client.ts
Comment thread src/instance-client.ts
Comment thread src/instance-client.ts
Comment thread src/instance-client.ts Outdated
Comment thread src/instance-client.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread src/instance-client.ts
clearTimeout(request.timeout);
request.reject(new Error('Connection closed during request'));
pendingRequests.delete(id);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 71920f3. Configure here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

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.

feat: Queue pending requests during WebSocket reconnection instead of dropping them

2 participants