fix(signal): critical fixes for identity key detection - batch 1

High Priority Fixes based on Copilot/Codex code review:

1. Propagate errorCode to shouldRecreateSession (CRITICAL)
   - Extract error attribute from retry node
   - Pass errorCode to shouldRecreateSession in both sendRetryRequest and sendMessagesAgain
   - Without this fix, MAC error detection was NOT working
   - Now immediate session recreation works for MAC errors

2. Use .unref() on metrics interval
   - Prevents blocking process exit in short-lived scripts/tests
   - Interval no longer keeps event loop alive unnecessarily

3. Reset circuit breaker regardless of state
   - Previously only reset when isOpen()
   - Now resets in any state (open, half-open, or closed with accumulated failures)
   - Ensures clean slate after identity change detection

https://claude.ai/code/session_01SWAcNuGZQmEKyBPYkBhVHg
This commit is contained in:
Claude
2026-01-30 12:32:56 +00:00
parent 164c7fbe93
commit 3dcdc7be69
2 changed files with 20 additions and 8 deletions
+15 -4
View File
@@ -452,12 +452,18 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
// Check if we have a session with this JID
const sessionId = signalRepository.jidToSignalProtocolAddress(fromJid)
const hasSession = await signalRepository.validateSession(fromJid)
const result = messageRetryManager.shouldRecreateSession(fromJid, hasSession.exists)
// Extract error code from retry node if present (for MAC error detection)
const retryNode = getBinaryNodeChild(node, 'retry')
const errorAttr = retryNode?.attrs?.error as string | undefined
const errorCode = messageRetryManager.parseRetryErrorCode(errorAttr)
const result = messageRetryManager.shouldRecreateSession(fromJid, hasSession.exists, errorCode)
shouldRecreateSession = result.recreate
recreateReason = result.reason
if (shouldRecreateSession) {
logger.debug({ fromJid, retryCount, reason: recreateReason }, 'recreating session for retry')
logger.debug({ fromJid, retryCount, reason: recreateReason, errorCode }, 'recreating session for retry')
// Delete existing session to force recreation
await authState.keys.set({ session: { [sessionId]: null } })
forceIncludeKeys = true
@@ -1006,12 +1012,17 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
const sessionId = signalRepository.jidToSignalProtocolAddress(participant)
const hasSession = await signalRepository.validateSession(participant)
const result = messageRetryManager.shouldRecreateSession(participant, hasSession.exists)
// Extract error code from retry node if present (for MAC error detection)
const errorAttr = retryNode?.attrs?.error as string | undefined
const errorCode = messageRetryManager.parseRetryErrorCode(errorAttr)
const result = messageRetryManager.shouldRecreateSession(participant, hasSession.exists, errorCode)
shouldRecreateSession = result.recreate
recreateReason = result.reason
if (shouldRecreateSession) {
logger.debug({ participant, retryCount, reason: recreateReason }, 'recreating session for outgoing retry')
logger.debug({ participant, retryCount, reason: recreateReason, errorCode }, 'recreating session for outgoing retry')
await authState.keys.set({ session: { [sessionId]: null } })
}
} catch (error) {