feat(cron): add default stagger controls for scheduled jobs

This commit is contained in:
Peter Steinberger
2026-02-17 23:46:05 +01:00
parent b98b113b88
commit c26cf6aa83
20 changed files with 907 additions and 56 deletions

View File

@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import { normalizeCronJobCreate, normalizeCronJobPatch } from "./normalize.js";
import { DEFAULT_TOP_OF_HOUR_STAGGER_MS } from "./stagger.js";
function expectNormalizedAtSchedule(scheduleInput: Record<string, unknown>) {
const normalized = normalizeCronJobCreate({
@@ -137,6 +138,40 @@ describe("normalizeCronJobCreate", () => {
expectNormalizedAtSchedule({ kind: "at", atMs: "2026-01-12T18:00:00" });
});
it("defaults cron stagger for recurring top-of-hour schedules", () => {
const normalized = normalizeCronJobCreate({
name: "hourly",
enabled: true,
schedule: { kind: "cron", expr: "0 * * * *", tz: "UTC" },
sessionTarget: "main",
wakeMode: "next-heartbeat",
payload: {
kind: "systemEvent",
text: "tick",
},
}) as unknown as Record<string, unknown>;
const schedule = normalized.schedule as Record<string, unknown>;
expect(schedule.staggerMs).toBe(DEFAULT_TOP_OF_HOUR_STAGGER_MS);
});
it("preserves explicit exact cron schedule", () => {
const normalized = normalizeCronJobCreate({
name: "exact",
enabled: true,
schedule: { kind: "cron", expr: "0 * * * *", tz: "UTC", staggerMs: 0 },
sessionTarget: "main",
wakeMode: "next-heartbeat",
payload: {
kind: "systemEvent",
text: "tick",
},
}) as unknown as Record<string, unknown>;
const schedule = normalized.schedule as Record<string, unknown>;
expect(schedule.staggerMs).toBe(0);
});
it("defaults deleteAfterRun for one-shot schedules", () => {
const normalized = normalizeCronJobCreate({
name: "default delete",
@@ -377,4 +412,13 @@ describe("normalizeCronJobPatch", () => {
}) as unknown as Record<string, unknown>;
expect(cleared.sessionKey).toBeNull();
});
it("normalizes cron stagger values in patch schedules", () => {
const normalized = normalizeCronJobPatch({
schedule: { kind: "cron", expr: "0 * * * *", staggerMs: "30000" },
}) as unknown as Record<string, unknown>;
const schedule = normalized.schedule as Record<string, unknown>;
expect(schedule.staggerMs).toBe(30_000);
});
});