feat(prekey): add destroy() method for proper resource cleanup

Implements PreKeyManager.destroy() to prevent memory leaks during connection cleanup.

Changes:
- Added PreKeyManager.destroy() method that clears and pauses all PQueues
- Exposed destroy() in SignalKeyStoreWithTransaction type
- Integrated destroy() call in addTransactionCapability() to cleanup both PreKeyManager and keyQueues
- Added keys.destroy() call in socket.ts end() function alongside other cleanup operations

Benefits:
- Prevents memory leaks from orphaned PQueues
- Proper cleanup of PreKeyManager resources during disconnect
- Consistent with existing cleanup pattern (circuit breakers, session manager)
- Zero impact on active connections (only called during cleanup)

Observability:
- Added debug logs for tracking cleanup operations
- Logs include queue type and cleanup status

Cross-file analysis:
- PreKeyManager instantiated in auth-utils.ts:130
- addTransactionCapability() called in socket.ts:499
- cleanup happens in socket.ts:836 (end function)

https://claude.ai/code/session_33db9e93-e4c3-4859-9ff3-96d8864af1c4
This commit is contained in:
Claude
2026-02-03 20:02:14 +00:00
parent 9d4442f053
commit 51a4b42f9c
4 changed files with 40 additions and 0 deletions
+3
View File
@@ -832,6 +832,9 @@ export const makeSocket = (config: SocketConfig) => {
// Clean up unified session manager
unifiedSessionManager?.destroy()
// Clean up transaction capability (PreKeyManager + queues)
keys.destroy?.()
ws.removeAllListeners('close')
ws.removeAllListeners('open')
ws.removeAllListeners('message')
+1
View File
@@ -99,6 +99,7 @@ export type SignalKeyStore = {
export type SignalKeyStoreWithTransaction = SignalKeyStore & {
isInTransaction: () => boolean
transaction<T>(exec: () => Promise<T>, key: string): Promise<T>
destroy?: () => void
}
export type TransactionCapabilityOptions = {
+19
View File
@@ -339,6 +339,25 @@ export const addTransactionCapability = (
} finally {
releaseTxMutexRef(key)
}
},
/**
* Cleanup all resources (queues, managers)
* Should be called during connection cleanup
*/
destroy: () => {
logger.debug('🗑️ Cleaning up transaction capability resources')
preKeyManager.destroy()
// Clear all key queues
keyQueues.forEach((queue, keyType) => {
queue.clear()
queue.pause()
logger.debug(`Queue for ${keyType} cleared and paused`)
})
keyQueues.clear()
logger.debug('Transaction capability cleanup completed')
}
}
}
+17
View File
@@ -123,4 +123,21 @@ export class PreKeyManager {
}
})
}
/**
* Cleanup all queues and resources
* Should be called during connection cleanup to prevent memory leaks
*/
destroy(): void {
this.logger.debug('🗑️ Destroying PreKeyManager')
this.queues.forEach((queue, keyType) => {
queue.clear()
queue.pause()
this.logger.debug(`Queue for ${keyType} cleared and paused`)
})
this.queues.clear()
this.logger.debug('PreKeyManager destroyed - all queues cleaned up')
}
}