feat: Session cleanup with activity tracking - Automated cleanup of inactive/orphaned Signal sessions

feat: Session cleanup with activity tracking - Automated cleanup of inactive/orphaned Signal sessions
This commit is contained in:
Renato Alcara
2026-02-10 07:03:45 -03:00
committed by GitHub
8 changed files with 1866 additions and 0 deletions
+11
View File
@@ -87,6 +87,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
notificationMutex,
receiptMutex,
signalRepository,
sessionActivityTracker,
query,
upsertMessage,
resyncAppState,
@@ -1531,6 +1532,16 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
: msgContent?.reactionMessage ? 'reaction'
: 'other'
recordMessageReceived(msgType)
// Track session activity for cleanup
if (sessionActivityTracker && msg.key.remoteJid) {
sessionActivityTracker.recordActivity(msg.key.remoteJid)
// For groups, also track participant activity
if (msg.key.participant) {
sessionActivityTracker.recordActivity(msg.key.participant)
}
}
})
} catch (error) {
logger.error({ error, node: binaryNodeToString(node) }, 'error in handling message')
+14
View File
@@ -86,6 +86,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
authState,
messageMutex,
signalRepository,
sessionActivityTracker,
upsertMessage,
query,
fetchPrivacySettings,
@@ -1511,6 +1512,19 @@ export const makeMessagesSocket = (config: SocketConfig) => {
if (messageRetryManager && !participant) {
messageRetryManager.addRecentMessage(destinationJid, msgId, message)
}
// Track session activity for cleanup (all target JIDs)
if (sessionActivityTracker) {
// Record activity for destination JID
sessionActivityTracker.recordActivity(destinationJid)
// For groups, also record activity for all participants who received the message
if (isGroup || isStatus) {
for (const device of devices) {
sessionActivityTracker.recordActivity(device.jid)
}
}
}
}, meId)
return msgId
+29
View File
@@ -6,12 +6,15 @@ import { proto } from '../../WAProto/index.js'
import {
DEF_CALLBACK_PREFIX,
DEF_TAG_PREFIX,
DEFAULT_SESSION_CLEANUP_CONFIG,
INITIAL_PREKEY_COUNT,
MIN_PREKEY_COUNT,
MIN_UPLOAD_INTERVAL,
NOISE_WA_HEADER,
UPLOAD_TIMEOUT
} from '../Defaults'
import { makeSessionCleanup } from '../Signal/session-cleanup'
import { makeSessionActivityTracker } from '../Signal/session-activity-tracker'
import type { ConnectionState, LIDMapping, SocketConfig } from '../Types'
import { DisconnectReason } from '../Types'
import {
@@ -499,6 +502,18 @@ export const makeSocket = (config: SocketConfig) => {
const keys = addTransactionCapability(authState.keys, logger, transactionOpts)
const signalRepository = makeSignalRepository({ creds, keys }, logger, pnFromLIDUSync)
// Session activity tracker - tracks last activity for cleanup (must be created first)
const sessionActivityTracker = makeSessionActivityTracker(keys, logger)
// Session cleanup manager - removes inactive/orphaned sessions
const sessionCleanup = makeSessionCleanup(
keys,
signalRepository.lidMapping,
sessionActivityTracker,
logger,
DEFAULT_SESSION_CLEANUP_CONFIG
)
let lastDateRecv: Date
let epoch = 1
let keepAliveReq: NodeJS.Timeout
@@ -1079,6 +1094,12 @@ export const makeSocket = (config: SocketConfig) => {
clearInterval(keepAliveReq)
clearTimeout(qrTimer)
// Stop session cleanup scheduler
sessionCleanup.stop()
// Stop session activity tracker and flush pending data
await sessionActivityTracker.stop()
// Clean up unified session manager
unifiedSessionManager?.destroy()
@@ -1448,6 +1469,12 @@ export const makeSocket = (config: SocketConfig) => {
recordConnectionAttempt('success')
incrementActiveConnections()
// Start session cleanup scheduler
sessionCleanup.start()
// Start session activity tracker
sessionActivityTracker.start()
// Update server time offset from success node
const serverTime = extractServerTime(node)
if (serverTime) {
@@ -1572,6 +1599,8 @@ export const makeSocket = (config: SocketConfig) => {
ev,
authState: { creds, keys },
signalRepository,
sessionCleanup,
sessionActivityTracker,
get user() {
return authState.creds.me
},