mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-30 14:26:53 +00:00
test(perf): trim repeated setup in cron memory and config suites
This commit is contained in:
@@ -38,7 +38,7 @@ function topOfHourOffsetMs(jobId: string) {
|
||||
let fixtureRoot = "";
|
||||
let fixtureCount = 0;
|
||||
|
||||
async function makeStorePath() {
|
||||
function makeStorePath() {
|
||||
const storePath = path.join(fixtureRoot, `case-${fixtureCount++}.jobs.json`);
|
||||
return {
|
||||
storePath,
|
||||
@@ -157,7 +157,6 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-02-06T10:05:00.000Z"));
|
||||
});
|
||||
@@ -168,7 +167,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("covers schedule updates and payload patching", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const cron = await startCronForStore({
|
||||
storePath: store.storePath,
|
||||
cronEnabled: false,
|
||||
@@ -214,7 +213,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("repairs isolated every jobs missing createdAtMs and sets nextWakeAtMs", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
await fs.writeFile(
|
||||
store.storePath,
|
||||
JSON.stringify({
|
||||
@@ -263,7 +262,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("repairs missing nextRunAtMs on non-schedule updates without touching other jobs", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const cron = await startCronForStore({ storePath: store.storePath, cronEnabled: false });
|
||||
|
||||
const created = await cron.add({
|
||||
@@ -287,7 +286,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("does not advance unrelated due jobs when updating another job", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const now = Date.parse("2026-02-06T10:05:00.000Z");
|
||||
vi.setSystemTime(now);
|
||||
const cron = await startCronForStore({ storePath: store.storePath, cronEnabled: false });
|
||||
@@ -329,7 +328,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("treats persisted jobs with missing enabled as enabled during update()", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const now = Date.parse("2026-02-06T10:05:00.000Z");
|
||||
await fs.writeFile(
|
||||
store.storePath,
|
||||
@@ -372,7 +371,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("treats persisted due jobs with missing enabled as runnable", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const now = Date.parse("2026-02-06T10:05:00.000Z");
|
||||
const dueAt = now - 30_000;
|
||||
await fs.writeFile(
|
||||
@@ -419,7 +418,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("caps timer delay to 60s for far-future schedules", async () => {
|
||||
const timeoutSpy = vi.spyOn(globalThis, "setTimeout");
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const cron = await startCronForStore({ storePath: store.storePath });
|
||||
|
||||
const callsBeforeAdd = timeoutSpy.mock.calls.length;
|
||||
@@ -444,7 +443,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("re-arms timer without hot-looping when a run is already in progress", async () => {
|
||||
const timeoutSpy = vi.spyOn(globalThis, "setTimeout");
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const now = Date.parse("2026-02-06T10:05:00.000Z");
|
||||
const state = createRunningCronServiceState({
|
||||
storePath: store.storePath,
|
||||
@@ -468,7 +467,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("skips forced manual runs while a timer-triggered run is in progress", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
let resolveRun:
|
||||
| ((value: { status: "ok" | "error" | "skipped"; summary?: string; error?: string }) => void)
|
||||
| undefined;
|
||||
@@ -529,7 +528,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("does not double-run a job when cron.run overlaps a due timer tick", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const runStarted = createDeferred<void>();
|
||||
const runFinished = createDeferred<void>();
|
||||
const runResolvers: Array<
|
||||
@@ -586,7 +585,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("does not advance unrelated due jobs after manual cron.run", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const nowMs = Date.now();
|
||||
const dueNextRunAtMs = nowMs - 1_000;
|
||||
|
||||
@@ -627,7 +626,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("keeps telegram delivery target writeback after manual cron.run", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const originalTarget = "https://t.me/obviyus";
|
||||
const rewrittenTarget = "-10012345/6789";
|
||||
const runIsolatedAgentJob = vi.fn(async (params: { job: { id: string } }) => {
|
||||
@@ -675,7 +674,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("#13845: one-shot jobs with terminal statuses do not re-fire on restart", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const pastAt = Date.parse("2026-02-06T09:00:00.000Z");
|
||||
const baseJob = {
|
||||
name: "reminder",
|
||||
@@ -732,7 +731,7 @@ describe("Cron issue regressions", () => {
|
||||
runIsolatedAgentJob: ReturnType<typeof vi.fn>;
|
||||
firstRetryAtMs: number;
|
||||
}> => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
id: params.id,
|
||||
name: "reminder",
|
||||
@@ -794,7 +793,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("#24355: one-shot job disabled after max transient retries", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-06T10:00:00.000Z");
|
||||
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
@@ -837,7 +836,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("#24355: one-shot job respects cron.retry config", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-06T10:00:00.000Z");
|
||||
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
@@ -883,7 +882,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("#24355: one-shot job disabled immediately on permanent error", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-06T10:00:00.000Z");
|
||||
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
@@ -920,7 +919,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("prevents spin loop when cron job completes within the scheduled second (#17821)", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
// Simulate a cron job "0 13 * * *" (daily 13:00 UTC) that fires exactly
|
||||
// at 13:00:00.000 and completes 7ms later (still in the same second).
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
@@ -970,7 +969,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("enforces a minimum refire gap for second-granularity cron schedules (#17821)", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
@@ -1008,7 +1007,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("treats timeoutSeconds=0 as no timeout for isolated agentTurn jobs", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
@@ -1055,7 +1054,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("does not time out agentTurn jobs at the default 10-minute safety window", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
@@ -1108,7 +1107,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("aborts isolated runs when cron timeout fires", async () => {
|
||||
vi.useRealTimers();
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
id: "abort-on-timeout",
|
||||
@@ -1147,7 +1146,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("suppresses isolated follow-up side effects after timeout", async () => {
|
||||
vi.useRealTimers();
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
const enqueueSystemEvent = vi.fn();
|
||||
|
||||
@@ -1201,7 +1200,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("applies timeoutSeconds to manual cron.run isolated executions", async () => {
|
||||
vi.useRealTimers();
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const abortAwareRunner = createAbortAwareIsolatedRunner();
|
||||
|
||||
const cron = await startCronForStore({
|
||||
@@ -1237,7 +1236,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("applies timeoutSeconds to startup catch-up isolated executions", async () => {
|
||||
vi.useRealTimers();
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
const cronJob = createIsolatedRegressionJob({
|
||||
id: "startup-timeout",
|
||||
@@ -1354,7 +1353,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("records per-job start time and duration for batched due jobs", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const dueAt = Date.parse("2026-02-06T10:05:01.000Z");
|
||||
const first = createDueIsolatedJob({ id: "batch-first", nowMs: dueAt, nextRunAtMs: dueAt });
|
||||
const second = createDueIsolatedJob({ id: "batch-second", nowMs: dueAt, nextRunAtMs: dueAt });
|
||||
@@ -1399,7 +1398,7 @@ describe("Cron issue regressions", () => {
|
||||
});
|
||||
|
||||
it("#17554: run() clears stale runningAtMs and executes the job", async () => {
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const now = Date.parse("2026-02-06T10:05:00.000Z");
|
||||
const staleRunningAtMs = now - 2 * 60 * 60 * 1000 - 1;
|
||||
|
||||
@@ -1455,7 +1454,7 @@ describe("Cron issue regressions", () => {
|
||||
|
||||
it("honors cron maxConcurrentRuns for due jobs", async () => {
|
||||
vi.useRealTimers();
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const dueAt = Date.parse("2026-02-06T10:05:01.000Z");
|
||||
const first = createDueIsolatedJob({ id: "parallel-first", nowMs: dueAt, nextRunAtMs: dueAt });
|
||||
const second = createDueIsolatedJob({
|
||||
@@ -1528,7 +1527,7 @@ describe("Cron issue regressions", () => {
|
||||
// job abort that fires much sooner than the configured outer timeout.
|
||||
it("outer cron timeout fires at configured timeoutSeconds, not at 1/3 (#29774)", async () => {
|
||||
vi.useRealTimers();
|
||||
const store = await makeStorePath();
|
||||
const store = makeStorePath();
|
||||
const scheduledAt = Date.parse("2026-02-15T13:00:00.000Z");
|
||||
|
||||
// Keep this short for suite speed while still separating expected timeout
|
||||
|
||||
Reference in New Issue
Block a user