72 lines
2.4 KiB
JavaScript
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?.();
|
|
}
|