Skip to content

feat(ext/cron): scaffold Deno.cron.persistent API (no backends yet)#33965

Open
bartlomieju wants to merge 1 commit into
mainfrom
feat/persistent-cron
Open

feat(ext/cron): scaffold Deno.cron.persistent API (no backends yet)#33965
bartlomieju wants to merge 1 commit into
mainfrom
feat/persistent-cron

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

First step toward persistent cron jobs in Deno — jobs that survive
process exit and reboot because they are registered with the host OS
scheduler (crontab on Linux, launchd on macOS, schtasks on Windows)
rather than kept alive by an in-process tokio loop. This PR lands the
public API surface and the Rust wiring only; every backend currently
returns "persistent cron is not yet supported on this platform". Per-OS
backends and the deno cron exec subcommand that the OS scheduler
invokes will follow in separate PRs.

Deno.cron.persistent, Deno.cron.remove, and Deno.cron.list are
namespace-attached methods on the existing Deno.cron function, so they
compose with the in-memory cron API. The worker entry point exports
default.scheduled(controller) matching the Cloudflare Workers Cron
Triggers shape. On the Rust side the deno_cron extension gains a
second generic P: PersistentCronHandler; for now only an
Unimplemented variant exists, returning CronError::Unsupported from
every method. Gated behind the existing --unstable-cron flag.

First step toward persistent cron jobs that survive process exit and
reboot via the host OS scheduler. Lands the public API surface and
Rust wiring only; all backends return "unsupported on this platform".

Adds `Deno.cron.persistent`, `Deno.cron.remove`, `Deno.cron.list` as
namespace-attached methods on the existing `Deno.cron` function, plus
a new `Deno.CronController` type for the worker entry point's
`default.scheduled` callback. The `deno_cron` extension grows a second
generic parameter `P: PersistentCronHandler` and a stub
`PersistentCronHandlerImpl::Unimplemented` variant; all four
`deno_cron::init` call sites pass it through.

Gated behind the existing `--unstable-cron` flag.
Copy link
Copy Markdown
Contributor

@fibibot fibibot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spec test tests/specs/run/unstable_cron_enabled is broken on every platform (Linux/macOS/Windows, debug + release). The test does console.log(scope, Deno.cron) and unstable_cron.enabled.out expects:

main [Function: cron]
worker [Function: cron]

but 01_cron.ts now unconditionally attaches persistent, remove, list to the function, so the actual output is main [Function: cron] { persistent: ..., remove: ..., list: ... }. Update the .out file to match.

Separately: the new surface has no positive test. Even with every backend returning Unsupported, a spec test that exercises Deno.cron.persistent(...) and asserts on the persistent cron is not yet supported on this platform error would lock in the JS-side validation paths (TypeError on missing name/schedule/script, non-string env values, etc.) before the per-OS backends land.

  • nit: op_cron_persistent_create calls validate_cron_name (≤ 64 chars), but JS-side persistent() only checks length > 0. The Rust error still surfaces, just less consistently than the other TypeErrors thrown from JS.
  • nit: permissions: string[] flows straight through to whatever follow-up backend will exec the worker. Worth deciding now whether anything other than --allow-* / --deny-* is rejected at registration — once a poisoned string is in a user's crontab/launchd plist it's painful to revoke.

@fibibot
Copy link
Copy Markdown
Contributor

fibibot commented May 14, 2026

specs::run::unstable_cron_enabled failure looks real — the new Deno.cron.persistent/remove/list methods make the output show [Function: cron] { persistent, remove, list } while unstable_cron.enabled.out still expects [Function: cron]. Needs the .out updated.

@lunadogbot
Copy link
Copy Markdown
Contributor

specs::run::unstable_cron_enabled failure looks real — the new Deno.cron.persistent/remove/list methods this PR adds now show up in the inspected Deno.cron function and no longer match unstable_cron.enabled.out ([Function: cron] vs [Function: cron] { persistent, remove, list }). Just needs the .out updated.

Copy link
Copy Markdown
Contributor

@lunadogbot lunadogbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. tests/specs/run/unstable_cron_enabled/unstable_cron.enabled.out still expects main [Function: cron] / worker [Function: cron], but 01_cron.ts now attaches persistent, remove, and list to Deno.cron. The test specs (1/2) failures are real; update the fixture to match the new inspected function shape.
  2. Deno.cron.persistent, Deno.cron.remove, and Deno.cron.list add public unstable API with no spec/unit coverage. Even while every backend returns unsupported, add a test that runs with --unstable-cron and covers the exposed methods plus the current unsupported error path.
  • nit: the new JSDoc blocks in lib.deno.unstable.d.ts do not include @param / @returns for persistent, remove, or list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants