mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 00:48:27 +00:00
fix(cron): fix timeout, add timestamp validation, enable file sync
Fixes #7667 Task 1: Fix cron operation timeouts - Increase default gateway tool timeout from 10s to 30s - Increase cron-specific tool timeout to 60s - Increase CLI default timeout from 10s to 30s - Prevents timeouts when gateway is busy with long-running jobs Task 2: Add timestamp validation - New validateScheduleTimestamp() function in validate-timestamp.ts - Rejects atMs timestamps more than 1 minute in the past - Rejects atMs timestamps more than 10 years in the future - Applied to both cron.add and cron.update operations - Provides helpful error messages with current time and offset Task 3: Enable file sync for manual edits - Track file modification time (storeFileMtimeMs) in CronServiceState - Check file mtime in ensureLoaded() and reload if changed - Recompute next runs after reload to maintain accuracy - Update mtime after persist() to prevent reload loop - Dashboard now picks up manual edits to ~/.openclaw/cron/jobs.json
This commit is contained in:
committed by
Peter Steinberger
parent
a749db9820
commit
3a03e38378
64
src/cron/validate-timestamp.ts
Normal file
64
src/cron/validate-timestamp.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { CronSchedule } from "./types.js";
|
||||
|
||||
const ONE_MINUTE_MS = 60 * 1000;
|
||||
const TEN_YEARS_MS = 10 * 365.25 * 24 * 60 * 60 * 1000;
|
||||
|
||||
export type TimestampValidationError = {
|
||||
ok: false;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type TimestampValidationSuccess = {
|
||||
ok: true;
|
||||
};
|
||||
|
||||
export type TimestampValidationResult = TimestampValidationSuccess | TimestampValidationError;
|
||||
|
||||
/**
|
||||
* Validates atMs timestamps in cron schedules.
|
||||
* Rejects timestamps that are:
|
||||
* - More than 1 minute in the past
|
||||
* - More than 10 years in the future
|
||||
*/
|
||||
export function validateScheduleTimestamp(
|
||||
schedule: CronSchedule,
|
||||
nowMs: number = Date.now(),
|
||||
): TimestampValidationResult {
|
||||
if (schedule.kind !== "at") {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const atMs = schedule.atMs;
|
||||
|
||||
if (typeof atMs !== "number" || !Number.isFinite(atMs)) {
|
||||
return {
|
||||
ok: false,
|
||||
message: `Invalid atMs: must be a finite number (got ${String(atMs)})`,
|
||||
};
|
||||
}
|
||||
|
||||
const diffMs = atMs - nowMs;
|
||||
|
||||
// Check if timestamp is in the past (allow 1 minute grace period)
|
||||
if (diffMs < -ONE_MINUTE_MS) {
|
||||
const nowDate = new Date(nowMs).toISOString();
|
||||
const atDate = new Date(atMs).toISOString();
|
||||
const minutesAgo = Math.floor(-diffMs / ONE_MINUTE_MS);
|
||||
return {
|
||||
ok: false,
|
||||
message: `atMs is in the past: ${atDate} (${minutesAgo} minutes ago). Current time: ${nowDate}`,
|
||||
};
|
||||
}
|
||||
|
||||
// Check if timestamp is too far in the future
|
||||
if (diffMs > TEN_YEARS_MS) {
|
||||
const atDate = new Date(atMs).toISOString();
|
||||
const yearsAhead = Math.floor(diffMs / (365.25 * 24 * 60 * 60 * 1000));
|
||||
return {
|
||||
ok: false,
|
||||
message: `atMs is too far in the future: ${atDate} (${yearsAhead} years ahead). Maximum allowed: 10 years`,
|
||||
};
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
Reference in New Issue
Block a user