import { db } from "./db/fcmTokens.js"; import { sendPushToDevice } from "./services/pushService.js"; import { errorMessage, formatElapsedMs } from "./util/formatElapsed.js"; let intervalId: ReturnType | undefined; export function startScheduler(): void { if (intervalId !== undefined) return; intervalId = setInterval(async () => { const passStarted = Date.now(); console.log("[Scheduler] Pass started"); try { const devices = await db.getAllForScheduler(); const seenTokens = new Set(); let checked = 0; let sent = 0; let skipped = 0; let failed = 0; let duplicates = 0; for (const d of devices) { if (seenTokens.has(d.fcmToken)) { duplicates++; continue; } seenTokens.add(d.fcmToken); checked++; const result = await sendPushToDevice(d.fcmToken); if (result === "sent") sent++; else if (result === "skipped") skipped++; else failed++; } const summaryParts = [ `Checked ${checked} devices`, `sent ${sent} pushes`, `skipped ${skipped}`, ]; if (failed > 0) summaryParts.push(`failed ${failed}`); if (duplicates > 0) { summaryParts.push(`${duplicates} duplicates ignored`); } console.log("[Scheduler]", summaryParts.join(", ")); console.log( "[Scheduler] Pass completed in", formatElapsedMs(Date.now() - passStarted) ); } catch (err) { console.error( "[Scheduler] Pass failed in", formatElapsedMs(Date.now() - passStarted) + ":", errorMessage(err) ); } }, 5 * 60 * 1000); } export function stopScheduler(): void { if (intervalId !== undefined) { clearInterval(intervalId); intervalId = undefined; } }