fix(repeater): stop reconnecting after the socket is torn down - #778
Conversation
A reconnection timer could fire after `disconnect()` had already dropped `_socket`, so `get socket` threw from inside `Timeout._onTimeout`. Nothing can catch a throw there, so it surfaced as a fatal uncaught exception: "Please make sure that repeater established a connection with host." `handleConnectionError` emitted `ERROR` and then unconditionally scheduled a reconnection. For `repeater_unauthorized` / `repeater_not_permitted` that emit is dispatched synchronously into the consumer, which treats the code as critical and calls `disconnect()` — so the reconnection was scheduled against a socket that no longer existed. Restore the early return for those terminal codes, since retrying an authorization rejection cannot succeed anyway. `scheduleReconnection` also overwrote `connectionTimer` without clearing the previous handle, leaking one timer per failed attempt. `disconnect()` could only cancel the last one, so every leaked timer fired and threw. Clear before scheduling to keep a single pending attempt. Additionally: - guard teardown with a `disposed` flag, checked before scheduling a reconnection and before the manual reconnect on `io server disconnect` - reach for `_socket` instead of the throwing getter in deferred callbacks (reconnection timer, `deploy`'s `nextTick`), so a late callback is a no-op - swap `MIN_RECONNECTION_DELAY` / `MAX_RECONNECTION_DELAY`, which were inverted (5s min vs 1s max). `Math.min(delay, MAX)` collapsed every backoff to 1s, and socket.io received `reconnectionDelay` above `reconnectionDelayMax` - drop manager listeners on teardown so a later `connect()` cannot double-register them on the cached manager
SummaryFixes the fatal Sentry issue
this.connectionTimer = setTimeout(() => this.socket.connect(), delay);
How it happens
if (data && this.suppressConnectionError(data)) {
this.events.emit(RepeaterServerEvents.ERROR, { ...data, message: err.message });
}
// Try reconnect in any case.
this.scheduleReconnection();
Control then returns to
This was a regression from #675, which removed the Why the volume is so highTwo amplifiers, both from #675:
Changes
TestsNew On Verification
Note, not addressed here
|
|
relates-to: #675