← Back to PRs

#3693: fix(cron): delete deleteAfterRun jobs regardless of execution status

by HirokiKobayashi-R open 2026-01-29 02:25 View on GitHub →
## Summary - Fixed infinite loop bug where `deleteAfterRun: true` one-shot jobs would loop every 40ms when skipped or failed - Changed deletion condition to trigger regardless of execution status (ok, skipped, or error) - Added tests for skipped and failed scenarios ## Problem One-shot jobs with `deleteAfterRun: true` were only deleted when `status === "ok"`. When the job was skipped or failed: - The job was not deleted (`shouldDelete = false`) - The job was not disabled (line 86-89 only handles `status === "ok"`) - `nextRunAtMs` remained in the past - Timer immediately re-fired → 40ms infinite loop ## Solution Changed `src/cron/service/timer.ts:82-83` from: ```typescript const shouldDelete = job.schedule.kind === "at" && status === "ok" && job.deleteAfterRun === true; ``` To: ```typescript const shouldDelete = job.schedule.kind === "at" && job.deleteAfterRun === true; ``` This matches the intended semantics of `deleteAfterRun: true` — "delete after execution regardless of outcome". ## Test plan - [x] Existing cron tests pass (54 tests) - [x] Added test: `deleteAfterRun: true` + `status: "skipped"` → job deleted - [x] Added test: `deleteAfterRun: true` + `status: "error"` → job deleted <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes an infinite re-run loop for one-shot (`schedule.kind === "at"`) jobs configured with `deleteAfterRun: true` by deleting them after execution regardless of whether they finished `ok`, `skipped`, or `error` (`src/cron/service/timer.ts`). It also extends the CronService test suite with new cases that verify delete-after-run behavior for skipped main-lane jobs loaded from disk and for isolated jobs that return an error status. <h3>Confidence Score: 4/5</h3> - This PR looks safe to merge and addresses a real runaway-timer scenario. - The production change is narrowly scoped (only affects deletion criteria for one-shot deleteAfterRun jobs) and is backed by new tests covering skipped and errored outcomes. The only concern is minor test robustness around stopping/cleanup ordering if CronService.stop ever becomes async. - src/cron/service.runs-one-shot-main-job-disables-it.test.ts <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs