mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 03:51:25 +00:00
fix: prevent duplicate cron runs across hot reloads
This commit is contained in:
@@ -1,11 +1,22 @@
|
||||
import type { CronServiceState } from "./state.js";
|
||||
|
||||
export async function locked<T>(state: CronServiceState, fn: () => Promise<T>): Promise<T> {
|
||||
const next = state.op.then(fn, fn);
|
||||
// Keep the chain alive even when the operation fails.
|
||||
state.op = next.then(
|
||||
const storeLocks = new Map<string, Promise<void>>();
|
||||
|
||||
const resolveChain = (promise: Promise<unknown>) =>
|
||||
promise.then(
|
||||
() => undefined,
|
||||
() => undefined,
|
||||
);
|
||||
|
||||
export async function locked<T>(state: CronServiceState, fn: () => Promise<T>): Promise<T> {
|
||||
const storePath = state.deps.storePath;
|
||||
const storeOp = storeLocks.get(storePath) ?? Promise.resolve();
|
||||
const next = Promise.all([resolveChain(state.op), resolveChain(storeOp)]).then(fn);
|
||||
|
||||
// Keep the chain alive even when the operation fails.
|
||||
const keepAlive = resolveChain(next);
|
||||
state.op = keepAlive;
|
||||
storeLocks.set(storePath, keepAlive);
|
||||
|
||||
return (await next) as T;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,15 @@ import type { CronJob } from "../types.js";
|
||||
import { inferLegacyName, normalizeOptionalText } from "./normalize.js";
|
||||
import type { CronServiceState } from "./state.js";
|
||||
|
||||
const storeCache = new Map<string, { version: 1; jobs: CronJob[] }>();
|
||||
|
||||
export async function ensureLoaded(state: CronServiceState) {
|
||||
if (state.store) return;
|
||||
const cached = storeCache.get(state.deps.storePath);
|
||||
if (cached) {
|
||||
state.store = cached;
|
||||
return;
|
||||
}
|
||||
const loaded = await loadCronStore(state.deps.storePath);
|
||||
const jobs = (loaded.jobs ?? []) as unknown as Array<Record<string, unknown>>;
|
||||
let mutated = false;
|
||||
@@ -35,6 +42,7 @@ export async function ensureLoaded(state: CronServiceState) {
|
||||
}
|
||||
}
|
||||
state.store = { version: 1, jobs: jobs as unknown as CronJob[] };
|
||||
storeCache.set(state.deps.storePath, state.store);
|
||||
if (mutated) await persist(state);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user