mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-20 05:31:30 +00:00
fix: preserve disabled cron jobs on restore
This commit is contained in:
@@ -133,4 +133,32 @@ describe("cron service store seam coverage", () => {
|
||||
expect(raw.jobs[0]?.jobId).toBe("repro-stable-id");
|
||||
expect(raw.jobs[0]?.id).toBeUndefined();
|
||||
});
|
||||
|
||||
it("preserves disabled jobs when persisted booleans roundtrip through string values", async () => {
|
||||
const { storePath } = await makeStorePath();
|
||||
|
||||
await writeSingleJobStore(storePath, {
|
||||
id: "disabled-string-job",
|
||||
name: "disabled string job",
|
||||
enabled: "false",
|
||||
createdAtMs: STORE_TEST_NOW - 60_000,
|
||||
updatedAtMs: STORE_TEST_NOW - 60_000,
|
||||
schedule: { kind: "every", everyMs: 60_000 },
|
||||
sessionTarget: "main",
|
||||
wakeMode: "now",
|
||||
payload: { kind: "systemEvent", text: "tick" },
|
||||
state: {},
|
||||
});
|
||||
|
||||
const before = await fs.readFile(storePath, "utf8");
|
||||
const state = createStoreTestState(storePath);
|
||||
|
||||
await ensureLoaded(state);
|
||||
|
||||
const job = findJobOrThrow(state, "disabled-string-job");
|
||||
expect(job.enabled).toBe(false);
|
||||
|
||||
const after = await fs.readFile(storePath, "utf8");
|
||||
expect(after).toBe(before);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import { normalizeCronJobIdentityFields } from "../normalize-job-identity.js";
|
||||
import { normalizeCronJobInput } from "../normalize.js";
|
||||
import { loadCronStore, saveCronStore } from "../store.js";
|
||||
import type { CronJob } from "../types.js";
|
||||
import { recomputeNextRuns } from "./jobs.js";
|
||||
@@ -34,11 +35,15 @@ export async function ensureLoaded(
|
||||
const fileMtimeMs = await getFileMtimeMs(state.deps.storePath);
|
||||
const loaded = await loadCronStore(state.deps.storePath);
|
||||
const jobs = (loaded.jobs ?? []) as unknown as CronJob[];
|
||||
for (const job of jobs) {
|
||||
for (const [index, job] of jobs.entries()) {
|
||||
const raw = job as unknown as Record<string, unknown>;
|
||||
const { legacyJobIdIssue } = normalizeCronJobIdentityFields(raw);
|
||||
const normalized = normalizeCronJobInput(raw);
|
||||
const hydrated =
|
||||
normalized && typeof normalized === "object" ? (normalized as unknown as CronJob) : job;
|
||||
jobs[index] = hydrated;
|
||||
if (legacyJobIdIssue) {
|
||||
const resolvedId = typeof raw.id === "string" ? raw.id : undefined;
|
||||
const resolvedId = typeof hydrated.id === "string" ? hydrated.id : undefined;
|
||||
state.deps.log.warn(
|
||||
{ storePath: state.deps.storePath, jobId: resolvedId },
|
||||
"cron: job used legacy jobId field; normalized id in memory (run openclaw doctor --fix to persist canonical shape)",
|
||||
@@ -46,8 +51,8 @@ export async function ensureLoaded(
|
||||
}
|
||||
// Persisted legacy jobs may predate the required `enabled` field.
|
||||
// Keep runtime behavior backward-compatible without rewriting the store.
|
||||
if (typeof job.enabled !== "boolean") {
|
||||
job.enabled = true;
|
||||
if (typeof hydrated.enabled !== "boolean") {
|
||||
hydrated.enabled = true;
|
||||
}
|
||||
}
|
||||
state.store = {
|
||||
|
||||
Reference in New Issue
Block a user