Files
email/sidecar/email-cron.ts
T
pastilhas 211e913501 a restart mid-sync stranded accounts at syncing or queued forever
getAllSyncedAccounts only picks up status = synced, so an account whose sidecar
process died between marking it syncing/queued and clearing that status again
dropped out of the cron and the IDLE watcher silently, with no error to explain
why background sync had stopped. Reset both on startup instead: the job runner
is in-memory, so neither state can be genuinely in flight in a fresh process.
2026-09-14 20:56:24 +01:00

49 lines
1.5 KiB
TypeScript

import { getUserById } from 'officerdb';
import { getAllSyncedAccounts, resetStuckSyncingAccounts } from '../db/queries';
import { performResync } from './resync';
const INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
let timer: ReturnType<typeof setInterval> | null = null;
async function tick() {
try {
const accounts = await getAllSyncedAccounts();
if (accounts.length === 0) return;
for (const account of accounts) {
const user = await getUserById(account.userId);
if (!user) continue;
try {
console.log(`[email-cron] Resyncing ${account.email}`);
const result = await performResync({ accountId: account.id, userEmail: user.email, userId: user.id });
if (result.saved > 0) {
console.log(`[email-cron] ${account.email}: ${result.saved} new emails`);
}
} catch (err) {
console.error(`[email-cron] Failed to resync ${account.email}:`, err instanceof Error ? err.message : err);
}
}
} catch (err) {
console.error('[email-cron] Error:', err instanceof Error ? err.message : err);
}
}
export function initEmailCron() {
if (timer) return;
resetStuckSyncingAccounts().catch((err) => {
console.error('[email-cron] Failed to reset stuck accounts:', err instanceof Error ? err.message : err);
});
console.log(`[email-cron] Starting email sync cron (every ${INTERVAL_MS / 60_000} min)`);
timer = setInterval(tick, INTERVAL_MS);
setTimeout(tick, 30_000);
}
export function stopEmailCron() {
if (timer) {
clearInterval(timer);
timer = null;
}
}