Merge 8d34bcf32e into 4583f88626
This commit is contained in:
commit
4812d1552e
@ -1,7 +1,16 @@
|
||||
import { Cron } from "croner";
|
||||
import type { CronSchedule } from "./types.js";
|
||||
|
||||
export function computeNextRunAtMs(schedule: CronSchedule, nowMs: number): number | undefined {
|
||||
export type ComputeNextRunOpts = {
|
||||
/** Default timezone to use when schedule.tz is not specified. */
|
||||
defaultTimezone?: string;
|
||||
};
|
||||
|
||||
export function computeNextRunAtMs(
|
||||
schedule: CronSchedule,
|
||||
nowMs: number,
|
||||
opts?: ComputeNextRunOpts,
|
||||
): number | undefined {
|
||||
if (schedule.kind === "at") {
|
||||
return schedule.atMs > nowMs ? schedule.atMs : undefined;
|
||||
}
|
||||
@ -17,8 +26,10 @@ export function computeNextRunAtMs(schedule: CronSchedule, nowMs: number): numbe
|
||||
|
||||
const expr = schedule.expr.trim();
|
||||
if (!expr) return undefined;
|
||||
// Use schedule.tz if specified, otherwise fall back to default timezone
|
||||
const timezone = schedule.tz?.trim() || opts?.defaultTimezone?.trim() || undefined;
|
||||
const cron = new Cron(expr, {
|
||||
timezone: schedule.tz?.trim() || undefined,
|
||||
timezone,
|
||||
catch: false,
|
||||
});
|
||||
const next = cron.nextRun(new Date(nowMs));
|
||||
|
||||
@ -33,19 +33,24 @@ export function findJobOrThrow(state: CronServiceState, id: string) {
|
||||
return job;
|
||||
}
|
||||
|
||||
export function computeJobNextRunAtMs(job: CronJob, nowMs: number): number | undefined {
|
||||
export function computeJobNextRunAtMs(
|
||||
job: CronJob,
|
||||
nowMs: number,
|
||||
opts?: { defaultTimezone?: string },
|
||||
): number | undefined {
|
||||
if (!job.enabled) return undefined;
|
||||
if (job.schedule.kind === "at") {
|
||||
// One-shot jobs stay due until they successfully finish.
|
||||
if (job.state.lastStatus === "ok" && job.state.lastRunAtMs) return undefined;
|
||||
return job.schedule.atMs;
|
||||
}
|
||||
return computeNextRunAtMs(job.schedule, nowMs);
|
||||
return computeNextRunAtMs(job.schedule, nowMs, { defaultTimezone: opts?.defaultTimezone });
|
||||
}
|
||||
|
||||
export function recomputeNextRuns(state: CronServiceState) {
|
||||
if (!state.store) return;
|
||||
const now = state.deps.nowMs();
|
||||
const defaultTimezone = state.deps.defaultTimezone;
|
||||
for (const job of state.store.jobs) {
|
||||
if (!job.state) job.state = {};
|
||||
if (!job.enabled) {
|
||||
@ -61,7 +66,7 @@ export function recomputeNextRuns(state: CronServiceState) {
|
||||
);
|
||||
job.state.runningAtMs = undefined;
|
||||
}
|
||||
job.state.nextRunAtMs = computeJobNextRunAtMs(job, now);
|
||||
job.state.nextRunAtMs = computeJobNextRunAtMs(job, now, { defaultTimezone });
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,6 +82,7 @@ export function nextWakeAtMs(state: CronServiceState) {
|
||||
|
||||
export function createJob(state: CronServiceState, input: CronJobCreate): CronJob {
|
||||
const now = state.deps.nowMs();
|
||||
const defaultTimezone = state.deps.defaultTimezone;
|
||||
const id = crypto.randomUUID();
|
||||
const job: CronJob = {
|
||||
id,
|
||||
@ -97,7 +103,7 @@ export function createJob(state: CronServiceState, input: CronJobCreate): CronJo
|
||||
},
|
||||
};
|
||||
assertSupportedJobSpec(job);
|
||||
job.state.nextRunAtMs = computeJobNextRunAtMs(job, now);
|
||||
job.state.nextRunAtMs = computeJobNextRunAtMs(job, now, { defaultTimezone });
|
||||
return job;
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,8 @@ export type CronServiceDeps = {
|
||||
log: Logger;
|
||||
storePath: string;
|
||||
cronEnabled: boolean;
|
||||
/** Default timezone (IANA) for cron schedules that don't specify their own. */
|
||||
defaultTimezone?: string;
|
||||
enqueueSystemEvent: (text: string, opts?: { agentId?: string }) => void;
|
||||
requestHeartbeatNow: (opts?: { reason?: string }) => void;
|
||||
runHeartbeatOnce?: (opts?: { reason?: string }) => Promise<HeartbeatRunResult>;
|
||||
|
||||
@ -43,9 +43,13 @@ export function buildGatewayCronService(params: {
|
||||
return { agentId, cfg: runtimeConfig };
|
||||
};
|
||||
|
||||
// Use userTimezone from config as default for cron schedules
|
||||
const defaultTimezone = params.cfg.agents?.defaults?.userTimezone;
|
||||
|
||||
const cron = new CronService({
|
||||
storePath,
|
||||
cronEnabled,
|
||||
defaultTimezone,
|
||||
enqueueSystemEvent: (text, opts) => {
|
||||
const { agentId, cfg: runtimeConfig } = resolveCronAgent(opts?.agentId);
|
||||
const sessionKey = resolveAgentMainSessionKey({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user