// services/callTest/sessionStore.js // In-memory call-test sessions (TTL ~30 min). import { logger } from '../../utils/logger.js'; const TTL_MS = 30 * 60 * 1000; const SWEEP_INTERVAL_MS = 60 * 1000; /** @typedef {'store'|'dial'} CallTestMode */ /** @typedef {'pending'|'in_progress'|'completed'|'failed'} CallTestStatus */ const _store = new Map(); /** * @param {string} testId * @param {object} data */ export function createSession(testId, data) { const session = { testId, status: 'pending', createdAt: Date.now(), events: {}, lastStep: null, reachedCore: false, failedAt: null, callSid: null, enrichment: { twilio: {}, cdr: {} }, ...data, }; _store.set(testId, session); return session; } export function getSession(testId) { return _store.get(testId) || null; } export function updateSession(testId, patch) { const cur = _store.get(testId); if (!cur) return null; const next = { ...cur, ...patch }; _store.set(testId, next); return next; } export function listActiveByDestination(dialNumber) { const norm = String(dialNumber || '').trim(); const out = []; for (const [, s] of _store) { if (s.dialNumber !== norm) continue; if (s.status === 'pending' || s.status === 'in_progress') out.push(s); } return out; } export function allSessions() { return [..._store.values()]; } const sweepHandle = setInterval(() => { const now = Date.now(); for (const [id, s] of _store.entries()) { const ts = s.createdAt || 0; if (now - ts > TTL_MS) { logger('calltest:cleanup', `Expired session ${id} (store=${s.storeNum || 'n/a'})`); _store.delete(id); } } }, SWEEP_INTERVAL_MS); if (typeof sweepHandle.unref === 'function') sweepHandle.unref(); export function _clearAllSessionsForTests() { _store.clear(); }