// Планировщик аудита целостности DI2: ежедневно в 03:00 (МСК) + первый запуск через 10 сек после старта. // Порт из удалённого server/finance/audit.ts (без node-cron, setInterval-проверка). import { runIntegrityAudit, getAuditHistory } from "./audit-agent"; const TICK_MS = 60_000; const MSK_OFFSET_MS = 3 * 60 * 60 * 1000; // МСК = UTC+3 const AUDIT_HOUR_MSK = 3; let lastRunDay: string | null = getAuditHistory()[0]?.timestamp ? new Date(new Date(getAuditHistory()[0].timestamp).getTime() + MSK_OFFSET_MS).toISOString().slice(0, 10) : null; let schedulerStarted = false; function mskToday(): string { return new Date(Date.now() + MSK_OFFSET_MS).toISOString().slice(0, 10); } function mskHourNow(): number { return new Date(Date.now() + MSK_OFFSET_MS).getUTCHours(); } async function tick(): Promise { const today = mskToday(); if (lastRunDay === today) return; // сегодня уже запускался if (mskHourNow() < AUDIT_HOUR_MSK) return; // ещё не наступило 03:00 по МСК lastRunDay = today; try { await runIntegrityAudit(); } catch (err) { console.error("[AUDIT-AGENT] Ошибка при выполнении аудита:", err); } } export function startAuditScheduler(): void { if (schedulerStarted) return; // защита от повторной регистрации роутов (тесты и т.п.) schedulerStarted = true; setInterval(() => { tick().catch((err) => console.error("[AUDIT-AGENT] Tick error:", err)); }, TICK_MS); console.log("[AUDIT-AGENT] Планировщик запущен (ежедневно в 03:00 по МСК)"); // Первый запуск через 10 секунд после старта сервера setTimeout(async () => { try { const result = await runIntegrityAudit(); lastRunDay = new Date(new Date(result.timestamp).getTime() + MSK_OFFSET_MS).toISOString().slice(0, 10); } catch (err) { console.error("[AUDIT-AGENT] Ошибка при начальном аудите:", err); } }, 10000); }