import { describe, expect, it, vi } from "vitest" ;
import { CronService } from "./service.js" ;
import {
createCronStoreHarness,
createNoopLogger,
installCronTestHooks,
} from "./service.test-harness.js" ;
const noopLogger = createNoopLogger();
const { makeStorePath } = createCronStoreHarness({ prefix: "openclaw-cron-" });
installCronTestHooks({
logger: noopLogger,
baseTimeIso: "2025-12-13T00:00:00.000Z" ,
});
describe("CronService" , () => {
it("avoids duplicate runs when two services share a store" , async () => {
const store = await makeStorePath();
const enqueueSystemEvent = vi.fn();
const requestHeartbeatNow = vi.fn();
const runIsolatedAgentJob = vi.fn(async () => ({ status: "ok" as const }));
const cronA = new CronService({
storePath: store.storePath,
cronEnabled: true ,
log: noopLogger,
enqueueSystemEvent,
requestHeartbeatNow,
runIsolatedAgentJob,
});
await cronA.start();
const atMs = Date.parse("2025-12-13T00:00:01.000Z" );
await cronA.add({
name: "shared store job" ,
enabled: true ,
schedule: { kind: "at" , at: new Date(atMs).toISOString() },
sessionTarget: "main" ,
wakeMode: "next-heartbeat" ,
payload: { kind: "systemEvent" , text: "hello" },
});
const cronB = new CronService({
storePath: store.storePath,
cronEnabled: true ,
log: noopLogger,
enqueueSystemEvent,
requestHeartbeatNow,
runIsolatedAgentJob,
});
await cronB.start();
vi.setSystemTime(new Date("2025-12-13T00:00:01.000Z" ));
await vi.runOnlyPendingTimersAsync();
await cronA.status();
await cronB.status();
expect(enqueueSystemEvent).toHaveBeenCalledTimes(1 );
expect(requestHeartbeatNow).toHaveBeenCalledTimes(1 );
cronA.stop();
cronB.stop();
await store.cleanup();
});
});
Messung V0.5 in Prozent C=99 H=97 G=97
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland