Skip to content

Fix: Clear PartySocket backoff timer and reconnect instantly on network regain - #1782

Merged
SatyamPandey-07 merged 1 commit into
SatyamPandey-07:mainfrom
revatikadam0607:feat/rev
Jul 24, 2026
Merged

Fix: Clear PartySocket backoff timer and reconnect instantly on network regain#1782
SatyamPandey-07 merged 1 commit into
SatyamPandey-07:mainfrom
revatikadam0607:feat/rev

Conversation

@revatikadam0607

@revatikadam0607 revatikadam0607 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #1435 — PartySocket was still waiting out its exponential backoff delay even after the browser's online event fired, causing a delayed reconnect instead of an immediate one.

Changes

  • Added an internal __worksphereForceReconnect method in partySocketReconnect.ts that clears any pending backoff timeout/promise and resolves it immediately (or calls _connect() directly if no timer is pending).
  • Registered a window online event listener inside attachJitteredBackoff that calls __worksphereForceReconnect when the socket isn't already connected.
  • Ensured pendingResolve is cleared alongside pendingTimeoutId in _clearTimeouts and _disconnect to avoid stale resolves.
  • Added a unit test verifying that firing the online event resolves the pending _wait() immediately instead of waiting for the full backoff delay.

Testing

  • Added it("clears the pending backoff timer and reconnects immediately on online event", ...) in partySocketReconnect.test.ts.
  • Ran existing test suite to confirm no regressions.

I've resolved the issue. Kindly review it, and if everything looks good, please consider merging the corresponding PR.

Hi @SatyamPandey-07 , could you please review this PR for a potential bonus label based on the metrics below? Thanks!
labels

Summary by CodeRabbit

  • Bug Fixes
    • Improved socket reconnection behavior when network connectivity is restored.
    • Pending reconnect delays are now canceled, allowing connections to resume promptly after the browser comes back online.
    • Prevented stale reconnection waits from completing after connection state changes.
  • Tests
    • Added coverage verifying immediate reconnection when the browser’s online event fires.

@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

@revatikadam0607 is attempting to deploy a commit to the pandeysatyam1802-gmailcom's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

🎉 Thank you for contributing to WorkSphere!

Please ensure:

✅ Tests pass
✅ No secrets committed
✅ Documentation updated


💡 Connect & Support:

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

attachJitteredBackoff now clears pending reconnect timers and wait resolvers when forcing reconnection. A browser online listener triggers immediate recovery for disconnected sockets, with a test covering prompt wait resolution.

Changes

PartySocket reconnect recovery

Layer / File(s) Summary
Backoff wait lifecycle
src/lib/partySocketReconnect.ts
Pending reconnect timers and promise resolvers are tracked and cleared consistently; forced reconnects resolve pending waits or call _connect.
Online event reconnect wiring
src/lib/partySocketReconnect.ts, src/__tests__/lib/partySocketReconnect.test.ts
The browser online event forces reconnection when the socket is not connected, and a test verifies prompt _wait() resolution.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels: good-issue, ECSoC26-L2

Suggested reviewers: satyampandey-07, ayush-0918, sanjanatech19

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: clearing PartySocket backoff and reconnecting immediately on network regain.
Linked Issues check ✅ Passed The changes address the linked bug by clearing the backoff timer, reconnecting on online, and adding a test.
Out of Scope Changes check ✅ Passed The described code changes stay focused on PartySocket reconnect behavior and the required test coverage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/partySocketReconnect.ts (1)

165-168: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clear the resolver when _connect cancels the wait.

A direct _connect() clears the timer but leaves pendingResolve live. A later online event can resolve that cancelled, stale _wait() and resume an obsolete reconnect path.

Proposed fix
       if (pendingTimeoutId) {
         clearTimeout(pendingTimeoutId);
         pendingTimeoutId = null;
       }
+      pendingResolve = null;
       originalConnect.call(this);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/partySocketReconnect.ts` around lines 165 - 168, Update the direct
_connect() cancellation path to clear pendingResolve alongside pendingTimeoutId,
ensuring a later online event cannot resolve the cancelled _wait() or resume the
obsolete reconnect flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/__tests__/lib/partySocketReconnect.test.ts`:
- Around line 140-173: Wrap the mocked-global setup and assertions in the test
around attachJitteredBackoff and _wait with a try/finally block. In the finally
clause, restore window.addEventListener from originalAddEventListener and return
Jest to real timers with jest.useRealTimers(), ensuring cleanup runs even when
the test fails.

---

Outside diff comments:
In `@src/lib/partySocketReconnect.ts`:
- Around line 165-168: Update the direct _connect() cancellation path to clear
pendingResolve alongside pendingTimeoutId, ensuring a later online event cannot
resolve the cancelled _wait() or resume the obsolete reconnect flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 24196553-ba24-4660-816d-5d82a5bea862

📥 Commits

Reviewing files that changed from the base of the PR and between 1a5d75b and 48fe38a.

📒 Files selected for processing (2)
  • src/__tests__/lib/partySocketReconnect.test.ts
  • src/lib/partySocketReconnect.ts

Comment on lines +140 to +173
jest.useFakeTimers();

let onlineHandler: (() => void) | undefined;
const originalAddEventListener = window.addEventListener;
window.addEventListener = jest.fn((event: string, cb: any) => {
if (event === "online") {
onlineHandler = cb;
}
}) as any;

const socket = {
_retryCount: 3,
_getNextDelay: () => 30_000,
_connect: jest.fn(),
_disconnect: jest.fn(),
_clearTimeouts: jest.fn(),
addEventListener: jest.fn(),
} as any;

attachJitteredBackoff(socket);

let resolved = false;
const waitPromise = socket._wait().then(() => {
resolved = true;
});

// Simulate the browser regaining network connection
onlineHandler?.();
await Promise.resolve();
await waitPromise;

expect(resolved).toBe(true);

window.addEventListener = originalAddEventListener;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- file outline ---'
ast-grep outline src/__tests__/lib/partySocketReconnect.test.ts --view expanded || true

echo '--- top of file with line numbers ---'
sed -n '1,260p' src/__tests__/lib/partySocketReconnect.test.ts | cat -n

echo '--- search for cleanup hooks in this file ---'
rg -n "afterEach|beforeEach|useRealTimers|restoreAllMocks|clearAllTimers|addEventListener =|removeEventListener" src/__tests__/lib/partySocketReconnect.test.ts || true

Repository: SatyamPandey-07/WorkSphere

Length of output: 10734


Restore the mocked globals in finally. A failure before cleanup can leave window.addEventListener mocked and fake timers enabled for later tests, making the suite order-dependent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/lib/partySocketReconnect.test.ts` around lines 140 - 173, Wrap
the mocked-global setup and assertions in the test around attachJitteredBackoff
and _wait with a try/finally block. In the finally clause, restore
window.addEventListener from originalAddEventListener and return Jest to real
timers with jest.useRealTimers(), ensuring cleanup runs even when the test
fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug [Medium/L2]: Fix party socket reconnect exponential backoff timer reset on network regain

2 participants