()
| 416 | |
| 417 | /** Start the TTL cleanup interval. Deletes stale sessions from the store. */ |
| 418 | export function startSessionCleanup(): void { |
| 419 | if (cleanupTimer) return; |
| 420 | cleanupTimer = setInterval(async () => { |
| 421 | try { |
| 422 | if (isDatabaseInitialized()) { |
| 423 | const { rowCount } = await getPool().query( |
| 424 | `DELETE FROM adcp_state WHERE collection = $1 AND updated_at < NOW() - ($2 || ' milliseconds')::interval`, |
| 425 | [SESSIONS_COLLECTION, String(SESSION_TTL_MS)], |
| 426 | ); |
| 427 | if ((rowCount ?? 0) > 0) { |
| 428 | logger.info({ deleted: rowCount }, 'Cleaned up expired training-agent sessions'); |
| 429 | } |
| 430 | const taskDeleted = await cleanupExpiredTasks(getPool()); |
| 431 | if (taskDeleted > 0) { |
| 432 | logger.info({ deleted: taskDeleted }, 'Cleaned up expired MCP tasks'); |
| 433 | } |
| 434 | const idempDeleted = await cleanupExpiredIdempotency(getPool()); |
| 435 | if (idempDeleted > 0) { |
| 436 | logger.info({ deleted: idempDeleted }, 'Cleaned up expired idempotency entries'); |
| 437 | } |
| 438 | } |
| 439 | } catch (err) { |
| 440 | logger.warn({ err }, 'Session/task cleanup failed'); |
| 441 | } |
| 442 | }, CLEANUP_INTERVAL_MS); |
| 443 | if (cleanupTimer.unref) cleanupTimer.unref(); |
| 444 | } |
| 445 | |
| 446 | export function stopSessionCleanup(): void { |
| 447 | if (cleanupTimer) { |
no test coverage detected