refactor(cron): dedupe next-run recompute loop

This commit is contained in:
Peter Steinberger
2026-02-16 01:27:40 +00:00
parent c95a61aa9d
commit 2679089e9e

View File

@@ -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) {