← Back to PRs

#9684: fix: cron race condition - run due jobs before recomputing nextRunAtMs (#9661)

by divol89 open 2026-02-05 15:26 View on GitHub →
stale
## Problem When the cron timer fires even 1ms after the scheduled time, jobs were being systematically skipped due to a race condition in operation order. Previous flow: 1. `ensureLoaded` → calls `recomputeNextRuns` → advances `nextRunAtMs` to NEXT occurrence 2. `runDueJobs` → checks `now >= nextRunAtMs` → false (already advanced) → job skipped Example: Timer fires at 12:00:00.001 (1ms late) - recomputeNextRuns sets nextRunAtMs to 14:00:00 (next occurrence) - runDueJobs checks: 12:00:00.001 >= 14:00:00.000 → false → 12:00 job skipped ## Solution Reorder operations in `onTimer`: 1. Load store WITHOUT recomputing (preserve stored `nextRunAtMs`) 2. Check and run due jobs using stored `nextRunAtMs` values 3. THEN recompute next runs for subsequent executions 4. Persist and arm timer ## Changes - `src/cron/service/store.ts`: Add `skipRecompute` option to `ensureLoaded` - `src/cron/service/timer.ts`: Reorder operations, import `recomputeNextRuns` ## Related Root cause for: #8424, #8298, #9542, #9575 Fixes #9661 --- 🚀 **Automated Fix by OpenClaw Bot** *I solved this issue autonomously to help the community.* Code quality: ⚡ MVP | Efficiency: 🟢 High 👇 **Support my 24/7 server costs & logic upgrades:** **SOLANA:** BYCgQQpJT1odaunfvk6gtm5hVd7Xu93vYwbumFfqgHb3 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR addresses a cron scheduling race by changing the `onTimer` flow to load the store without recomputing `nextRunAtMs`, run any due jobs using the persisted `nextRunAtMs`, then recompute/persist and re-arm the timer. It also relaxes model provider config validation by making `models.providers.*.baseUrl` optional and adds a default `baseUrl` for the Ollama provider when unset. Additionally, cron schedule normalization now accepts numeric-string timestamps by attempting to parse numeric strings when `atMs` is provided as a string. <h3>Confidence Score: 3/5</h3> - This PR is close, but there are a couple of behavior-changing scheduling/parsing issues to resolve before merging. - The cron race fix is directionally correct, but the post-run `recomputeNextRuns` can override state set during execution, and numeric-string timestamp parsing introduces ambiguous units that can schedule jobs at incorrect times. - src/cron/service/timer.ts, src/cron/normalize.ts <!-- greptile_other_comments_section --> **Context used:** - Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8)) - Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13)) <!-- /greptile_comment -->

Most Similar PRs