Groups cdr_feed legs by Correlation ID for call-level summaries, fixes report-column field parsing and Docker proxy routing, and adds /calltest post-call Twilio and CDR enrichment. Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
1.8 KiB
JavaScript
76 lines
1.8 KiB
JavaScript
// 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();
|
|
}
|