fix(cron): preserve overrides and harden next-run calculation

This commit is contained in:
Peter Steinberger
2026-02-16 23:31:26 +00:00
parent 968bba5c18
commit b3d0e0cb45
3 changed files with 5 additions and 11 deletions

View File

@@ -150,12 +150,8 @@ describe("resolveCronSession", () => {
"webhook:stable-key": {
updatedAt: Date.now() - 1000,
modelOverride: "some-model",
} as unknown as {
sessionId: string;
updatedAt: number;
modelOverride?: string;
},
});
} as ReturnType<typeof loadSessionStore>);
vi.mocked(evaluateSessionFreshness).mockReturnValue({ fresh: true });
const result = resolveCronSession({

View File

@@ -59,9 +59,8 @@ export function resolveCronSession(params: {
}
const sessionEntry: SessionEntry = {
// Spread existing entry to preserve conversation context when reusing
// (the spread already copies all fields when !isNewSession, no need to re-assign)
...(isNewSession ? undefined : entry),
// Preserve existing per-session overrides even when rolling to a new sessionId.
...entry,
// Always update these core fields
sessionId,
updatedAt: params.nowMs,

View File

@@ -62,13 +62,12 @@ export function computeNextRunAtMs(schedule: CronSchedule, nowMs: number): numbe
}
// Guard against same-second rescheduling loops: if croner returns
// "now" (or an earlier instant) when the job completed mid-second,
// retry from the next whole second.
// "now" (or an earlier instant), retry from the next whole second.
const nextSecondMs = Math.floor(nowMs / 1000) * 1000 + 1000;
const retry = cron.nextRun(new Date(nextSecondMs));
if (!retry) {
return undefined;
}
const retryMs = retry.getTime();
return Number.isFinite(retryMs) ? retryMs : undefined;
return Number.isFinite(retryMs) && retryMs > nowMs ? retryMs : undefined;
}