feat: cron ISO at + delete-after-run
This commit is contained in:
@@ -193,6 +193,7 @@ export class CronService {
|
||||
name: normalizeRequiredName(input.name),
|
||||
description: normalizeOptionalText(input.description),
|
||||
enabled: input.enabled !== false,
|
||||
deleteAfterRun: input.deleteAfterRun,
|
||||
createdAtMs: now,
|
||||
updatedAtMs: now,
|
||||
schedule: input.schedule,
|
||||
@@ -229,6 +230,8 @@ export class CronService {
|
||||
if ("description" in patch)
|
||||
job.description = normalizeOptionalText(patch.description);
|
||||
if (typeof patch.enabled === "boolean") job.enabled = patch.enabled;
|
||||
if (typeof patch.deleteAfterRun === "boolean")
|
||||
job.deleteAfterRun = patch.deleteAfterRun;
|
||||
if (patch.schedule) job.schedule = patch.schedule;
|
||||
if (patch.sessionTarget) job.sessionTarget = patch.sessionTarget;
|
||||
if (patch.wakeMode) job.wakeMode = patch.wakeMode;
|
||||
@@ -472,6 +475,8 @@ export class CronService {
|
||||
job.state.lastError = undefined;
|
||||
this.emit({ jobId: job.id, action: "started", runAtMs: startedAt });
|
||||
|
||||
let deleted = false;
|
||||
|
||||
const finish = async (
|
||||
status: "ok" | "error" | "skipped",
|
||||
err?: string,
|
||||
@@ -484,14 +489,21 @@ export class CronService {
|
||||
job.state.lastDurationMs = Math.max(0, endedAt - startedAt);
|
||||
job.state.lastError = err;
|
||||
|
||||
if (job.schedule.kind === "at" && status === "ok") {
|
||||
// One-shot job completed successfully; disable it.
|
||||
job.enabled = false;
|
||||
job.state.nextRunAtMs = undefined;
|
||||
} else if (job.enabled) {
|
||||
job.state.nextRunAtMs = this.computeJobNextRunAtMs(job, endedAt);
|
||||
} else {
|
||||
job.state.nextRunAtMs = undefined;
|
||||
const shouldDelete =
|
||||
job.schedule.kind === "at" &&
|
||||
status === "ok" &&
|
||||
job.deleteAfterRun === true;
|
||||
|
||||
if (!shouldDelete) {
|
||||
if (job.schedule.kind === "at" && status === "ok") {
|
||||
// One-shot job completed successfully; disable it.
|
||||
job.enabled = false;
|
||||
job.state.nextRunAtMs = undefined;
|
||||
} else if (job.enabled) {
|
||||
job.state.nextRunAtMs = this.computeJobNextRunAtMs(job, endedAt);
|
||||
} else {
|
||||
job.state.nextRunAtMs = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
this.emit({
|
||||
@@ -505,6 +517,12 @@ export class CronService {
|
||||
nextRunAtMs: job.state.nextRunAtMs,
|
||||
});
|
||||
|
||||
if (shouldDelete && this.store) {
|
||||
this.store.jobs = this.store.jobs.filter((j) => j.id !== job.id);
|
||||
deleted = true;
|
||||
this.emit({ jobId: job.id, action: "removed" });
|
||||
}
|
||||
|
||||
if (job.sessionTarget === "isolated") {
|
||||
const prefix = job.isolation?.postToMainPrefix?.trim() || "Cron";
|
||||
const body = (summary ?? err ?? status).trim();
|
||||
@@ -592,7 +610,7 @@ export class CronService {
|
||||
await finish("error", String(err));
|
||||
} finally {
|
||||
job.updatedAtMs = nowMs;
|
||||
if (!opts.forced && job.enabled) {
|
||||
if (!opts.forced && job.enabled && !deleted) {
|
||||
// Keep nextRunAtMs in sync in case the schedule advanced during a long run.
|
||||
job.state.nextRunAtMs = this.computeJobNextRunAtMs(
|
||||
job,
|
||||
|
||||
Reference in New Issue
Block a user