fix: clear stale routingInfo on restart to prevent slow/unstable connections

fix: clear stale routingInfo on restart to prevent slow/unstable connections
This commit is contained in:
Renato Alcara
2026-02-25 01:49:25 -03:00
committed by GitHub
parent be34c5136d
commit f4daa9197d
+23 -7
View File
@@ -182,9 +182,13 @@ export const makeSocket = (config: SocketConfig) => {
// assigns a fresh edge server on this connection. This fixes sessions that became slow
// after a pm2 restart because the previous edge server retained stale state.
// Signal keys and auth credentials are NOT affected — no QR re-scan is needed.
// hadStaleRoutingInfo is used below to skip the offline buffer on reconnect scenarios
// (same channel, new QR scan) so live messages are not held hostage by the backlog buffer.
let hadStaleRoutingInfo = false
if (config.clearRoutingInfoOnStart && authState?.creds?.routingInfo) {
logger.info('clearRoutingInfoOnStart: discarding stored routingInfo to force fresh edge server assignment')
authState.creds.routingInfo = undefined
hadStaleRoutingInfo = true
}
if (url.protocol === 'wss' && authState?.creds?.routingInfo) {
@@ -1558,11 +1562,11 @@ export const makeSocket = (config: SocketConfig) => {
const [reasonNode] = getAllBinaryNodeChildren(node)
const { reason, statusCode } = getErrorCodeFromStreamError(node)
if(reason === 'device_removed') {
if (reason === 'device_removed') {
logger.error({ node }, 'stream error: device removed — logging out')
} else if(reason === 'xml-not-well-formed') {
} else if (reason === 'xml-not-well-formed') {
logger.warn({ node }, 'stream error: sent malformed stanza (xml-not-well-formed)')
} else if(reason === 'ack') {
} else if (reason === 'ack') {
logger.warn({ ackId: reasonNode?.attrs?.id, node }, 'stream error: ack-based error')
} else {
logger.error({ reason, statusCode, node }, 'stream errored out')
@@ -1611,13 +1615,18 @@ export const makeSocket = (config: SocketConfig) => {
// Prometheus / history consolidation) and is typically set to 5-30 s by operators.
// This constant must remain short regardless so that a large offline backlog cannot
// hold live incoming messages hostage for minutes.
const OFFLINE_BUFFER_TIMEOUT_MS = 5_000
// When clearRoutingInfoOnStart cleared a stale routingInfo, this is a reconnect of an
// existing session (same channel, new QR scan after disconnect). In this case we skip
// the offline buffer entirely so live messages are not held hostage waiting for the
// server to finish flushing the pending-message backlog (CB:ib,,offline).
// For normal restarts (no stale routingInfo) the standard 5 s safety cap applies.
const OFFLINE_BUFFER_TIMEOUT_MS = hadStaleRoutingInfo ? 0 : 5_000
let offlineBufferTimeout: NodeJS.Timeout | undefined
process.nextTick(() => {
if (creds.me?.id) {
if (creds.me?.id && !hadStaleRoutingInfo) {
// start buffering important events
// if we're logged in
// if we're logged in (and this is not a reconnect-after-stale-routing)
ev.buffer()
didStartBuffer = true
@@ -1626,11 +1635,18 @@ export const makeSocket = (config: SocketConfig) => {
offlineBufferTimeout = setTimeout(() => {
offlineBufferTimeout = undefined
if (didStartBuffer) {
logger.warn({ timeoutMs: OFFLINE_BUFFER_TIMEOUT_MS }, 'perf: offline-buffer safety timeout reached, force-flushing before CB:ib,,offline')
logger.warn(
{ timeoutMs: OFFLINE_BUFFER_TIMEOUT_MS },
'perf: offline-buffer safety timeout reached, force-flushing before CB:ib,,offline'
)
ev.flush()
didStartBuffer = false
}
}, OFFLINE_BUFFER_TIMEOUT_MS)
} else if (creds.me?.id && hadStaleRoutingInfo) {
logger.info(
'clearRoutingInfoOnStart: skipping offline buffer — reconnect scenario, messages will be delivered immediately'
)
}
ev.emit('connection.update', { connection: 'connecting', receivedPendingNotifications: false, qr: undefined })