fix(socket): clear stuck "Reconnecting" indicator after invite accept#4919
fix(socket): clear stuck "Reconnecting" indicator after invite accept#4919waleedlatif1 wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview
Token mint errors in the auth callback always complete the handshake with Reviewed by Cursor Bugbot for commit b27dca7. Configure here. |
Greptile SummaryFixes a stuck "Reconnecting…" indicator that appeared after an invite-accept redirect, where a transient token-minting failure during org-switch was latched as a permanent auth failure. The fix fast-fails the handshake on any token error, adds bounded exponential-backoff retry for namespace rejections, and ensures the
Confidence Score: 5/5Safe to merge — the change is contained to the socket reconnection path, all event handlers remain registered on the same socket instance, and the bounded retry cap prevents endless re-minting. The auth-failure recovery path is now deterministic: tokens are always fast-failed to the server, inactive-socket errors are handled by a capped backoff loop, and the connect handler always clears isReconnecting. The retryConnection fix is straightforward. No data loss, no new async races, and the cap correctly bounds the worst-case behaviour for a genuine logged-out session. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as SocketProvider
participant SIO as Socket.IO Client
participant API as /api/auth/socket-token
participant SRV as Socket.IO Server
UI->>SIO: "io(url, { auth: async cb })"
SIO->>API: generateSocketToken()
alt Token minted OK
API-->>SIO: token
SIO->>SRV: connect (token)
SRV-->>SIO: connect_error (bad token)
SIO-->>UI: "connect_error (socket.active = false)"
UI->>UI: scheduleAuthRetry(socket, attempt++)
Note over UI: backoff delay (1s to 30s)
UI->>SIO: socket.connect()
else Token mint failed (any error)
API-->>SIO: throws
SIO->>SRV: connect (token: null)
SRV-->>SIO: namespace rejection
SIO-->>UI: "connect_error (socket.active = false)"
UI->>UI: scheduleAuthRetry(socket, attempt++)
end
alt "Retry succeeds (attempt < 10)"
SIO->>SRV: connect (fresh token)
SRV-->>SIO: connect OK
SIO-->>UI: connect event
UI->>UI: clearIsReconnecting, resetAttemptCounter
else "Retries exhausted (attempt >= 10)"
UI->>UI: setAuthFailed(true), stop retrying
Note over UI: User must call retryConnection() or reload
end
opt Manual retryConnection()
UI->>UI: reset counter, setAuthFailed(false)
UI->>SIO: socket.connect()
end
Reviews (2): Last reviewed commit: "fix(socket): recover from denied handsha..." | Re-trigger Greptile |
Accepting an invite switches the active org and immediately redirects into the workspace, so the socket bootstraps under a just-rotated session. A transient token-mint failure during that window left the realtime socket stuck showing "Reconnecting..." until a manual page reload. Follow the documented socket.io pattern and branch connect_error on socket.active. A server-denied handshake (active === false — e.g. a null or expired token rejected by the auth middleware, which destroys the socket and does not auto-reconnect) now retries socket.connect() with capped exponential backoff, re-running the auth callback to mint a fresh token. This recovers a transient failure on the next attempt and bounds a genuine logout to MAX_AUTH_RETRY_ATTEMPTS before latching authFailed for a manual reload. The connect handler clears isReconnecting so a healthy socket never shows it. Replaces the prior error-message sniffing and socket teardown/rebuild.
bc83720 to
b27dca7
Compare
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit b27dca7. Configure here.
|
Closing — this is already fixed more completely on That fix and this PR independently converged on the same idiomatic client pattern (branch Letting the complete fix reach staging via the normal dev → staging flow instead of landing a partial, duplicate client change here. |
Summary
connect_erroronsocket.active.active === true(transport/network blip) → let socket.io auto-reconnect (unchanged).active === false(server-denied handshake — a null/expired token rejected by the auth middleware destroys the socket and disables auto-reconnect) → retrysocket.connect()with capped exponential backoff, which re-runs theauthcallback to mint a fresh token.MAX_AUTH_RETRY_ATTEMPTS(10, ~3 min) before latchingauthFailedfor a manual reload — no infinite re-minting.connecthandler now clearsisReconnecting, so a healthy socket can never sit showing "Reconnecting…".socket.activesignal +socket.connect()manual reconnect.Type of Change
Testing
Tested manually. Biome clean, existing
app/workspace/providerstests pass (14/14), typecheck clean. Diagnostic logs (Retrying socket connection after denied handshake,Socket auth retries exhausted…) are included to confirm behavior on the next real occurrence.Checklist