diff --git a/src/cron/service/jobs.ts b/src/cron/service/jobs.ts index 3db5c3ebe58..fa1b6a15783 100644 --- a/src/cron/service/jobs.ts +++ b/src/cron/service/jobs.ts @@ -127,7 +127,10 @@ function normalizeJobTickState(params: { state: CronServiceState; job: CronJob; return { changed, skip: false }; } -export function recomputeNextRuns(state: CronServiceState): boolean { +function walkSchedulableJobs( + state: CronServiceState, + fn: (params: { job: CronJob; nowMs: number }) => boolean, +): boolean { if (!state.store) { return false; } @@ -141,6 +144,16 @@ export function recomputeNextRuns(state: CronServiceState): boolean { if (tick.skip) { continue; } + if (fn({ job, nowMs: now })) { + changed = true; + } + } + return changed; +} + +export function recomputeNextRuns(state: CronServiceState): boolean { + return walkSchedulableJobs(state, ({ job, nowMs: now }) => { + let changed = false; // Only recompute if nextRunAtMs is missing or already past-due. // Preserving a still-future nextRunAtMs avoids accidentally advancing // a job that hasn't fired yet (e.g. during restart recovery). @@ -179,8 +192,8 @@ export function recomputeNextRuns(state: CronServiceState): boolean { } } } - } - return changed; + return changed; + }); } /** @@ -191,19 +204,8 @@ export function recomputeNextRuns(state: CronServiceState): boolean { * (see #13992). */ export function recomputeNextRunsForMaintenance(state: CronServiceState): boolean { - if (!state.store) { - return false; - } - let changed = false; - const now = state.deps.nowMs(); - for (const job of state.store.jobs) { - const tick = normalizeJobTickState({ state, job, nowMs: now }); - if (tick.changed) { - changed = true; - } - if (tick.skip) { - continue; - } + return walkSchedulableJobs(state, ({ job, nowMs: now }) => { + let changed = false; // Only compute missing nextRunAtMs, do NOT recompute existing ones. // If a job was past-due but not found by findDueJobs, recomputing would // cause it to be silently skipped. @@ -214,8 +216,8 @@ export function recomputeNextRunsForMaintenance(state: CronServiceState): boolea changed = true; } } - } - return changed; + return changed; + }); } export function nextWakeAtMs(state: CronServiceState) {