fix(socketio): clear the 5s emit timer on acknowledgement - #410
Open
RobertoReale wants to merge 1 commit into
Open
fix(socketio): clear the 5s emit timer on acknowledgement#410RobertoReale wants to merge 1 commit into
RobertoReale wants to merge 1 commit into
Conversation
Every promisified `emit` starts a 5s timer and never clears it. The race is already settled when the acknowledgement arrives, so the late `reject` is a no-op, but the timer stays pending for 5s after *every* call and still runs its callback — which makes it impossible to report timeouts without also reporting calls that succeeded. Also: - bind the call to the socket it was emitted on: `init()` replaces `this.socket` when the handshake scheme changes, and a call left on the old socket can never be acknowledged, so its timeout is expected and must not be logged as a failure; - log rejected emits through `stringifyError`, so a server-side error object no longer reaches the user as `Unable to write file ... ([object Object])`.
RobertoReale
force-pushed
the
fix/emit-timeout-timer-leak
branch
from
August 19, 2026 08:22
1743e99 to
f8d4e63
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Fixes #405
Problem
The promisified
emitstarts a 5 s timer per call and never clears it:When the acknowledgement arrives the race is already settled, so the late
rejectis a no-op and nothing is visible — but a timer stays pending for 5 s after every emit and still runs its callback. On a path that runs continuously while editing (joinDoc,applyOtUpdate,clientTracking.*) that is one live timer per call, and it makes the timeout impossible to instrument: adding any log to that callback reports a failure for every successful call, 5 s late. That is exactly what happened while I was debugging this extension — the console filled with'applyOtUpdate' timed out after 5sfor saves that had been acknowledged in ~150 ms and had already appeared on overleaf.com.Two related points, both in the same few lines:
init()replacesthis.socketwhen the handshake scheme changes (v1 → v2 on overleaf.com). A call emitted on the previous socket can never be acknowledged, so its timer always fires even though the call was abandoned by design; binding the call to the socket it was emitted on tells the two cases apart.Unable to write file ... ([object Object]), hiding the actual message.Change
clearTimeoutin the acknowledgement callback;socketAtEmitand emit on it, so a timeout on a socket that has since been replaced is not reported as a failure;stringifyErrorhelper (name/code/message, falling back to JSON), instead of letting[object Object]reach the user.Verification
Against overleaf.com with 0.15.10 + this patch, tracing socket.io 0.9 packets: every emit that asks for an ack (
5:<id>+::…) gets itsack ackId=<id>back, and no timeout is logged any more — before the fix the same session produced ~20 spurious timeout lines. The one call that legitimately never completes (thejoinProjectqueued on the v1 socket that overleaf.com rejects) is now silent instead of printing an error.