feat(plugins): cron surface — declarations + scheduled() handler (Phase 4)#842
Open
lane711 wants to merge 1 commit into
Open
feat(plugins): cron surface — declarations + scheduled() handler (Phase 4)#842lane711 wants to merge 1 commit into
lane711 wants to merge 1 commit into
Conversation
…se 4)
Let plugins declare scheduled work as data and dispatch it from the Worker's
scheduled() handler. Like Payload's jobs queue, declaring a schedule runs nothing
by itself: on Workers the execution mechanism is a Cron Trigger delivered to
scheduled(), which this fans out to matching plugins.
- plugins/cron.ts: CronDeclaration ({ schedule, hookFamily }) + structural
CronablePlugin (crons[] + async onCronTick). collectCrons/collectCronSchedules
flatten declarations (wrangler sync + diagnostics). dispatchCronTick() matches a
fired expression to plugins, tags each onCronTick with the matched hookFamily
(one call per matching declaration), error-isolated. createScheduledHandler()
returns a CF scheduled(controller, env, ctx) handler reaching services via the
env-independent singletons (cron has no c.env), passing Worker env through and
waitUntil-ing the work.
Tests: cron.test.ts (12): collect/flatten, match-only-fired-cron, well-formed
event, unmatched reporting, multi-cron fan-out, error isolation, and the scheduled
handler (dispatch + waitUntil + env passthrough + lazy list + disabled no-op).
Full core suite 1552 passed, 0 failed; tsc clean.
Wiring scheduled() into the consumer Worker export + wrangler trigger generation
is a DX change deferred to the definePlugin()/docs bundle (Phase 5/7).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jun 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the plugin cron surface on top of the foundation (#841). Plugins declare scheduled work as data; a
scheduled()handler fans fired Cron Triggers out to the matching plugins.Infrastructure only — no consumer change yet. Like the other foundation phases, this is live-but-inert: no plugin declares
cronsyet, and thescheduledexport isn't wired into the consumer Worker.What's here
plugins/cron.ts:CronDeclaration { schedule, hookFamily }+ structuralCronablePlugin(crons[]+ asynconCronTick).collectCrons()/collectCronSchedules()— flatten declarations (for wrangler-trigger sync + diagnostics).dispatchCronTick()— matches a fired expression to the plugins that declared it, tags eachonCronTickwith the matchedhookFamily(one call per matching declaration), error-isolated.createScheduledHandler({ plugins, getHooks, disabled })— returns a Cloudflarescheduled(controller, env, ctx)handler that reaches services via the env-independent singletons (cron has noc.env), passes Workerenvthrough, andwaitUntils the work.Design note
Matches Payload's jobs model: declaring a
scheduleruns nothing by itself — the execution mechanism is the Cloudflare Cron Trigger delivered toscheduled(). The consumer still lists the expressions inwrangler.toml [triggers]; the plugincrons[]are the source of truth for which plugin owns which expression.Tests
cron.test.ts(12): collect/flatten + malformed-entry skipping, match-only-fired-cron, well-formed event, unmatched reporting, multi-cron fan-out (one call per declaration), error isolation, and thescheduledhandler (dispatch +waitUntil+ env passthrough + lazy list +disabledno-op).tsc --noEmit: cleanDeferred
Wiring
scheduledinto the consumer Worker export (export default { fetch, scheduled }) + starter template +wrangler.tomltrigger generation — bundled withdefinePlugin()/docs (Phase 5/7).🤖 Generated with Claude Code