mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
refactor(cron): remove auto migration wrapper
This commit is contained in:
@@ -9,7 +9,7 @@ const autoMigrateLegacyState = vi.hoisted(() =>
|
||||
const autoMigrateLegacyTaskStateSidecars = vi.hoisted(() =>
|
||||
vi.fn(async () => ({ migrated: true, skipped: false, changes: ["task-imported"], warnings: [] })),
|
||||
);
|
||||
const autoMigrateLegacyCronStore = vi.hoisted(() =>
|
||||
const repairLegacyCronStoreWithoutPrompt = vi.hoisted(() =>
|
||||
vi.fn(async () => ({ changes: ["cron-imported"], warnings: [] })),
|
||||
);
|
||||
const readConfigFileSnapshot = vi.hoisted(() =>
|
||||
@@ -31,8 +31,8 @@ vi.mock("./doctor-state-migrations.js", () => ({
|
||||
autoMigrateLegacyTaskStateSidecars,
|
||||
}));
|
||||
|
||||
vi.mock("./doctor/cron/auto-migration.js", () => ({
|
||||
autoMigrateLegacyCronStore,
|
||||
vi.mock("./doctor/cron/index.js", () => ({
|
||||
repairLegacyCronStoreWithoutPrompt,
|
||||
}));
|
||||
|
||||
vi.mock("../config/io.js", () => ({
|
||||
@@ -54,7 +54,7 @@ describe("runDoctorConfigPreflight state migration", () => {
|
||||
|
||||
expect(autoMigrateLegacyStateDir).toHaveBeenCalledOnce();
|
||||
expect(readConfigFileSnapshot).toHaveBeenCalledOnce();
|
||||
expect(autoMigrateLegacyCronStore).toHaveBeenCalledWith({
|
||||
expect(repairLegacyCronStoreWithoutPrompt).toHaveBeenCalledWith({
|
||||
cfg: { gateway: { mode: "local", port: 19091 } },
|
||||
});
|
||||
expect(autoMigrateLegacyState).toHaveBeenCalledWith({
|
||||
@@ -100,7 +100,7 @@ describe("runDoctorConfigPreflight state migration", () => {
|
||||
});
|
||||
|
||||
expect(autoMigrateLegacyState).not.toHaveBeenCalled();
|
||||
expect(autoMigrateLegacyCronStore).not.toHaveBeenCalled();
|
||||
expect(repairLegacyCronStoreWithoutPrompt).not.toHaveBeenCalled();
|
||||
expect(autoMigrateLegacyTaskStateSidecars).toHaveBeenCalledWith({ env: process.env });
|
||||
expect(note).toHaveBeenCalledWith("- task-imported", "Doctor changes");
|
||||
});
|
||||
|
||||
@@ -16,19 +16,19 @@ import { noteIncludeConfinementWarning } from "./doctor-config-analysis.js";
|
||||
import { findDoctorLegacyConfigIssues } from "./doctor/shared/legacy-config-issues.js";
|
||||
|
||||
type DoctorStateMigrationsModule = typeof import("./doctor-state-migrations.js");
|
||||
type DoctorCronAutoMigrationModule = typeof import("./doctor/cron/auto-migration.js");
|
||||
type DoctorCronModule = typeof import("./doctor/cron/index.js");
|
||||
|
||||
let doctorStateMigrationsPromise: Promise<DoctorStateMigrationsModule> | null = null;
|
||||
let doctorCronAutoMigrationPromise: Promise<DoctorCronAutoMigrationModule> | null = null;
|
||||
let doctorCronPromise: Promise<DoctorCronModule> | null = null;
|
||||
|
||||
function loadDoctorStateMigrations(): Promise<DoctorStateMigrationsModule> {
|
||||
doctorStateMigrationsPromise ??= import("./doctor-state-migrations.js");
|
||||
return doctorStateMigrationsPromise;
|
||||
}
|
||||
|
||||
function loadDoctorCronAutoMigration(): Promise<DoctorCronAutoMigrationModule> {
|
||||
doctorCronAutoMigrationPromise ??= import("./doctor/cron/auto-migration.js");
|
||||
return doctorCronAutoMigrationPromise;
|
||||
function loadDoctorCron(): Promise<DoctorCronModule> {
|
||||
doctorCronPromise ??= import("./doctor/cron/index.js");
|
||||
return doctorCronPromise;
|
||||
}
|
||||
|
||||
async function maybeMigrateLegacyConfig(): Promise<string[]> {
|
||||
@@ -182,8 +182,8 @@ export async function runDoctorConfigPreflight(
|
||||
const baseConfig = snapshot.sourceConfig ?? snapshot.config ?? {};
|
||||
if (options.migrateState !== false) {
|
||||
if (snapshot.valid) {
|
||||
const { autoMigrateLegacyCronStore } = await loadDoctorCronAutoMigration();
|
||||
const cronResult = await autoMigrateLegacyCronStore({ cfg: baseConfig });
|
||||
const { repairLegacyCronStoreWithoutPrompt } = await loadDoctorCron();
|
||||
const cronResult = await repairLegacyCronStoreWithoutPrompt({ cfg: baseConfig });
|
||||
noteStateMigrationResult(cronResult);
|
||||
}
|
||||
const { autoMigrateLegacyState, autoMigrateLegacyTaskStateSidecars } =
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
import { loadCronStore } from "../../../cron/store.js";
|
||||
import { autoMigrateLegacyCronStore } from "./auto-migration.js";
|
||||
|
||||
let tempRoot: string | null = null;
|
||||
|
||||
async function makeTempStorePath() {
|
||||
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-cron-auto-migration-"));
|
||||
return path.join(tempRoot, "cron", "jobs.json");
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
if (tempRoot) {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
tempRoot = null;
|
||||
}
|
||||
});
|
||||
|
||||
function createCronConfig(storePath: string): OpenClawConfig {
|
||||
return {
|
||||
cron: {
|
||||
store: storePath,
|
||||
webhook: "https://example.invalid/cron-finished",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function writeLegacyCronStore(storePath: string) {
|
||||
await fs.mkdir(path.dirname(storePath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
jobs: [
|
||||
{
|
||||
jobId: "legacy-job",
|
||||
name: "Legacy job",
|
||||
notify: true,
|
||||
createdAtMs: Date.parse("2026-02-01T00:00:00.000Z"),
|
||||
updatedAtMs: Date.parse("2026-02-02T00:00:00.000Z"),
|
||||
schedule: { kind: "cron", cron: "0 7 * * *", tz: "UTC" },
|
||||
payload: { kind: "systemEvent", text: "Morning brief" },
|
||||
state: {},
|
||||
},
|
||||
],
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
}
|
||||
|
||||
function requireRecord(value: unknown, label: string): Record<string, unknown> {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
throw new Error(`expected ${label}`);
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
describe("autoMigrateLegacyCronStore", () => {
|
||||
it("imports legacy cron jobs into SQLite and archives the legacy store", async () => {
|
||||
const storePath = await makeTempStorePath();
|
||||
await writeLegacyCronStore(storePath);
|
||||
|
||||
const result = await autoMigrateLegacyCronStore({ cfg: createCronConfig(storePath) });
|
||||
|
||||
const [job] = (await loadCronStore(storePath)).jobs as unknown as Array<
|
||||
Record<string, unknown>
|
||||
>;
|
||||
expect(job?.id).toBe("legacy-job");
|
||||
expect(job?.jobId).toBeUndefined();
|
||||
expect(requireRecord(job?.delivery, "cron delivery").mode).toBe("webhook");
|
||||
await expect(fs.stat(`${storePath}.migrated`)).resolves.toBeTruthy();
|
||||
expect(result.changes.join("\n")).toContain("Cron store migrated to SQLite");
|
||||
expect(result.warnings).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import { repairLegacyCronStoreWithoutPrompt, type LegacyCronRepairResult } from "./index.js";
|
||||
|
||||
export type CronAutoMigrationResult = LegacyCronRepairResult;
|
||||
|
||||
export async function autoMigrateLegacyCronStore(params: {
|
||||
cfg: OpenClawConfig;
|
||||
}): Promise<CronAutoMigrationResult> {
|
||||
return await repairLegacyCronStoreWithoutPrompt(params);
|
||||
}
|
||||
Reference in New Issue
Block a user