import cron from "node-cron"; import { env } from "./config.js"; import { runAuditLowConfidenceJob } from "./jobs/audit-low-confidence.js"; import { runTransformCorrectionsJob } from "./jobs/transform-corrections.js"; import { TechStepLlmService } from "./llm-verdict.js"; import { loadTechStepTaxonomy } from "./tech-step-taxonomy.js"; /** * Runs one full cycle: fetch the taxonomy, load the model, run both jobs, * dispose the model. The model is never kept loaded between scheduled * runs (see `llm-verdict.ts`'s `dispose()` doc comment) — this function's * own duration (model load/dispose easily adds several seconds) is an * accepted cost of keeping this process's idle RAM footprint low between * runs, not something to optimize away. */ export async function runOnce(): Promise { console.info("[tech-step-llm-worker] starting scheduled run..."); const taxonomy = await loadTechStepTaxonomy(); const techStepKeys = taxonomy.map((techStep) => techStep.key); const llm = new TechStepLlmService(); try { await llm.initialize(techStepKeys); const auditCount = await runAuditLowConfidenceJob(llm, { locale: env.TECH_STEP_WORKER_LOCALE, limit: env.TECH_STEP_WORKER_BATCH_LIMIT, }); console.info(`[tech-step-llm-worker] audit-low-confidence: ${auditCount} suggestion(s)`); const correctionCount = await runTransformCorrectionsJob(llm, { limit: env.TECH_STEP_WORKER_BATCH_LIMIT, }); console.info(`[tech-step-llm-worker] transform-corrections: ${correctionCount} suggestion(s)`); } finally { await llm.dispose(); } console.info("[tech-step-llm-worker] scheduled run complete."); } /** * Starts the long-lived cron loop — {@link runOnce} fires on * `env.TECH_STEP_WORKER_CRON`'s schedule, indefinitely, until the process * is stopped. A run that throws is logged, not left to crash the process — * the next scheduled fire still happens; a transient API/model failure on * one run shouldn't permanently kill the worker until someone notices and * manually restarts its container. */ export function startScheduler(): void { console.info(`[tech-step-llm-worker] scheduling runs on "${env.TECH_STEP_WORKER_CRON}"`); cron.schedule(env.TECH_STEP_WORKER_CRON, () => { runOnce().catch((err: unknown) => { console.error("[tech-step-llm-worker] scheduled run failed:", err); }); }); }