import { agentRequest } from './agentClient.js'; import { createAuditEvent, createJobHistory, listDueSchedules, markScheduleRun, nextRunFrom } from './store.js'; let timer = null; export function startScheduler() { if (timer) return; timer = setInterval(runDueSchedules, 30 * 1000); timer.unref?.(); runDueSchedules(); } async function runDueSchedules() { const now = new Date(); const schedules = listDueSchedules(now); for (const schedule of schedules) { try { const node = { id: schedule.node_id, name: schedule.node_name, baseUrl: schedule.base_url, token: schedule.token, }; const result = await agentRequest(node, `/backup/${encodeURIComponent(schedule.vm_name)}`, { method: 'POST' }); const historyId = createJobHistory({ node, vmName: schedule.vm_name, type: 'scheduled-backup', agentJobId: result?.jobId, status: 'accepted' }); createAuditEvent({ action: 'scheduled-backup', targetType: 'vm', targetId: `${node.id}:${schedule.vm_name}`, details: { scheduleId: schedule.id, historyId, agentJobId: result?.jobId } }); markScheduleRun(schedule.id, { lastRunAt: now.toISOString(), lastError: '', nextRunAt: nextRunFrom(now, schedule.interval_hours, schedule.time_of_day), }); } catch (error) { markScheduleRun(schedule.id, { lastRunAt: schedule.last_run_at, lastError: String(error.message || error), nextRunAt: new Date(now.getTime() + 5 * 60 * 1000).toISOString(), }); } } }