Files
poshmanager/server/services/runPlanScheduleWorker.js
2026-06-25 20:57:09 -05:00

72 lines
2.4 KiB
JavaScript

import { getStringSetting } from '../models/settingsModel.js';
import {
listDueRunPlanSchedules,
recordRunPlanScheduleDispatch
} from '../models/runPlanScheduleModel.js';
import { executeRunPlan } from './powershellRunner.js';
import { logger } from './logger.js';
let timer = null;
let running = false;
export function runPlanScheduleIntervalMinutes() {
const minutes = Number(getStringSetting('runplan_schedule_interval_minutes', process.env.RUNPLAN_SCHEDULE_INTERVAL_MINUTES || '1'));
return Number.isFinite(minutes) ? minutes : 1;
}
export async function dispatchDueRunPlanSchedules({ nowIso = new Date().toISOString(), signal } = {}) {
const due = listDueRunPlanSchedules(nowIso);
const summary = { evaluated: due.length, dispatched: 0, skipped: 0, errors: 0 };
for (const schedule of due) {
if (signal?.aborted) {
summary.skipped += 1;
break;
}
try {
const job = executeRunPlan(schedule.runplanId, schedule.createdBy || schedule.ownerUserId || null);
recordRunPlanScheduleDispatch(schedule, {
jobId: job.id,
plannedFor: schedule.nextRunAt || nowIso,
status: 'queued',
message: `Scheduled RunPlan ${schedule.runplanName || schedule.runplanId} queued as ${job.id}.`
});
summary.dispatched += 1;
} catch (error) {
recordRunPlanScheduleDispatch(schedule, {
plannedFor: schedule.nextRunAt || nowIso,
status: 'failed',
message: error.message
});
summary.errors += 1;
logger.error('runplan schedule dispatch failed', { scheduleId: schedule.id, error: error.message });
}
}
return summary;
}
export function startRunPlanScheduleWorker() {
const minutes = runPlanScheduleIntervalMinutes();
if (minutes <= 0) return null;
running = true;
scheduleNext(minutes);
logger.info(`runplan schedule dispatcher scheduled every ${minutes} minute(s)`);
return timer;
}
export function stopRunPlanScheduleWorker() {
running = false;
if (timer) clearTimeout(timer);
timer = null;
}
function scheduleNext(minutes) {
if (!running || minutes <= 0) return;
timer = setTimeout(() => {
dispatchDueRunPlanSchedules()
.then((summary) => logger.info('runplan schedule dispatch complete', summary))
.catch((error) => logger.error('runplan schedule dispatch failed', { error: error.message }))
.finally(() => scheduleNext(runPlanScheduleIntervalMinutes()));
}, minutes * 60 * 1000);
timer.unref?.();
}