import { db, withSuperAdmin } from "../db"; import { sql } from "drizzle-orm"; import { logger } from "../utils/logger"; /** * Retention журнала ошибок API (таблица error_logs, см. shared/schema.ts). * * Раз в сутки удаляет записи старше RETENTION_DAYS дней. Без отдельной * миграции: таблица и индексы уже существуют. Таймер unref'нут, чтобы * не удерживать процесс (и не мешать тестам завершаться). * Первый запуск — сразу при старте, дальше — каждые 24 часа. */ const log = logger("error-logs-retention"); const TICK_MS = 24 * 60 * 60 * 1000; // раз в сутки const RETENTION_DAYS = 30; let isRunning = false; async function cleanup(): Promise { // withSuperAdmin — единая точка для фоновых задач вне контекста организации const result = await withSuperAdmin(() => db.execute(sql` DELETE FROM error_logs WHERE created_at < now() - make_interval(days => ${RETENTION_DAYS}) `) ); const deleted = (result as { rowCount?: number }).rowCount ?? 0; if (deleted > 0) { log.info(`Удалено устаревших записей error_logs: ${deleted} (старше ${RETENTION_DAYS} дней)`); } else { log.debug(`Устаревших записей error_logs нет (старше ${RETENTION_DAYS} дней)`); } } export function startErrorLogsRetention(): void { if (isRunning) return; isRunning = true; const timer = setInterval(() => { cleanup().catch((err) => log.error("Cleanup error:", err)); }, TICK_MS); timer.unref?.(); // Первый прогон сразу после старта (в фоне, не блокируя listen) cleanup().catch((err) => log.error("Initial cleanup error:", err)); log.info(`started (retention ${RETENTION_DAYS} дней, тик раз в сутки)`); }