mirror of
https://github.com/openclaw/openclaw.git
synced 2026-09-28 05:54:09 +08:00
fix(cron): align regression fixtures with Gateway scheduler
Complete the test dependency migration after #159099 merged alongside both history fixtures and the startup recovery service/lazy proxy. Drive startup recovery with the existing joined scheduler clock instead of polling detached fake-timer callbacks. Inject an actual schedule-call failure and prove that work due during suspension runs exactly once after resume. Production startup recovery and Gateway scheduler behavior remain unchanged. Validation: all 25 pnpm tsgo:core:test shards; all cron tests plus server-cron-lazy and both cron.history suites (263 files, 3400 tests); changed-file checks, formatting, lint, and independent review. The focused start-arm run passed all 3 cases in 18.29s wall time (1.6s test time). Audited all CronService/lazy-cron callers under src, extensions, and test.
This commit is contained in:
@@ -8,7 +8,10 @@ import type { CliDeps } from "../../cli/deps.types.js";
|
||||
import { createLazyGatewayCronState } from "../../gateway/server-cron-lazy.js";
|
||||
import type { GatewayCronState } from "../../gateway/server-cron.js";
|
||||
import { openOpenClawStateDatabase } from "../../state/openclaw-state-db.js";
|
||||
import { createTestGatewayScheduler } from "../../test-utils/gateway-scheduler-clock.js";
|
||||
import {
|
||||
createGatewaySchedulerClock,
|
||||
createTestGatewayScheduler,
|
||||
} from "../../test-utils/gateway-scheduler-clock.js";
|
||||
import { CronService } from "../service.js";
|
||||
import { saveCronStore } from "../store.js";
|
||||
|
||||
@@ -50,12 +53,13 @@ it.each([
|
||||
}
|
||||
const enqueueSystemEvent = vi.fn();
|
||||
const log = { ...noopLogger, debug: vi.fn(), warn: vi.fn() };
|
||||
const clock = createGatewaySchedulerClock(now);
|
||||
const scheduler = createTestGatewayScheduler(clock.clock);
|
||||
if (failArm) {
|
||||
log.debug.mockImplementationOnce(() => {
|
||||
vi.spyOn(scheduler, "schedule").mockImplementationOnce(() => {
|
||||
throw new Error("secondary arm failure");
|
||||
});
|
||||
}
|
||||
const scheduler = createTestGatewayScheduler("fake-timers");
|
||||
const service = new CronService({
|
||||
scheduler,
|
||||
storePath,
|
||||
@@ -75,10 +79,10 @@ it.each([
|
||||
reconcileSystemJobs: async () => "converged",
|
||||
};
|
||||
const { cron } = createLazyGatewayCronState({
|
||||
scheduler,
|
||||
cfg: {},
|
||||
deps: {} as CliDeps,
|
||||
broadcast: vi.fn(),
|
||||
scheduler,
|
||||
});
|
||||
try {
|
||||
if (failWrite) {
|
||||
@@ -95,16 +99,12 @@ it.each([
|
||||
database.exec("DROP TRIGGER IF EXISTS reject_startup_terminal_write");
|
||||
expect(enqueueSystemEvent.mock.calls.map(([text]) => text)).toEqual(["overdue"]);
|
||||
cron.pauseScheduling();
|
||||
await vi.advanceTimersByTimeAsync(1_000);
|
||||
await clock.advanceBy(15_000);
|
||||
expect(enqueueSystemEvent.mock.calls.map(([text]) => text)).toEqual(["overdue"]);
|
||||
cron.resumeScheduling();
|
||||
await vi.advanceTimersByTimeAsync(15_000);
|
||||
await vi.waitFor(() =>
|
||||
expect(enqueueSystemEvent.mock.calls.map(([text]) => text)).toEqual([
|
||||
"overdue",
|
||||
"upcoming",
|
||||
]),
|
||||
);
|
||||
await vi.advanceTimersByTimeAsync(60_000);
|
||||
await clock.advanceBy(15_000);
|
||||
expect(enqueueSystemEvent.mock.calls.map(([text]) => text)).toEqual(["overdue", "upcoming"]);
|
||||
await clock.advanceBy(60_000);
|
||||
expect(enqueueSystemEvent.mock.calls.map(([text]) => text)).toEqual(["overdue", "upcoming"]);
|
||||
} finally {
|
||||
cron.stop();
|
||||
|
||||
@@ -4,6 +4,7 @@ import { createOperationalRunInstanceRef } from "../../agents/admitted-run-conte
|
||||
import { cronRunLogEntryToDetail } from "../../cron/run-history-detail.js";
|
||||
import { CronService } from "../../cron/service.js";
|
||||
import { createNoopLogger } from "../../cron/service.test-harness.js";
|
||||
import { createTestGatewayScheduler } from "../../test-utils/gateway-scheduler-clock.js";
|
||||
import { createDirectChatContext } from "../server-chat.agent-events.test-helpers.js";
|
||||
import { cronHistoryHandler } from "./cron-history.js";
|
||||
import { cronHandlers } from "./cron.js";
|
||||
@@ -71,6 +72,7 @@ it.each([
|
||||
"$method rechecks $change authority before final publication",
|
||||
async ({ method, change }) => {
|
||||
const cron = new CronService({
|
||||
scheduler: createTestGatewayScheduler(),
|
||||
storePath: "/synthetic/cron",
|
||||
cronEnabled: false,
|
||||
defaultAgentId: "main",
|
||||
|
||||
@@ -17,6 +17,7 @@ import { createNoopLogger } from "../../cron/service.test-harness.js";
|
||||
import { cronStoreKey } from "../../cron/store/key.js";
|
||||
import { ensureProfileForEmail } from "../../state/user-profiles.js";
|
||||
import { createTaskFixture } from "../../tasks/task-registry.test-support.js";
|
||||
import { createTestGatewayScheduler } from "../../test-utils/gateway-scheduler-clock.js";
|
||||
import {
|
||||
forbidMainThreadSql,
|
||||
observeMainThreadSql,
|
||||
@@ -85,6 +86,7 @@ async function setup() {
|
||||
"jobs.json",
|
||||
);
|
||||
const cron = new CronService({
|
||||
scheduler: createTestGatewayScheduler(),
|
||||
storePath,
|
||||
defaultAgentId: "main",
|
||||
cronEnabled: false,
|
||||
|
||||
Reference in New Issue
Block a user