Cron Jobs
Stratal integrates with Cloudflare Cron Triggers to run scheduled tasks. You define jobs as injectable classes that implement the CronJob interface, register them in a module, and Stratal handles matching, execution, and error collection.
Add cron triggers to your wrangler.jsonc. Each entry defines a schedule expression:
{ "triggers": { "crons": [ "0 2 * * *", "*/15 * * * *" ] }}No module import is required for cron support. The CronManager is registered as a core service automatically. You only need to create job classes and add them to a module’s jobs array.
Creating a cron job
Section titled “Creating a cron job”A cron job is a class that implements the CronJob interface:
import { Transient, inject } from 'stratal/di'import type { CronJob } from 'stratal/cron'import { LOGGER_TOKENS, type LoggerService } from 'stratal/logger'
@Transient()export class CleanupJob implements CronJob { readonly schedule = '0 2 * * *' // Daily at 2 AM UTC
constructor( @inject(LOGGER_TOKENS.LoggerService) private readonly logger: LoggerService, ) {}
async execute(controller: ScheduledController) { this.logger.info('Running daily cleanup', { scheduledTime: controller.scheduledTime, }) // perform cleanup logic }
async onError(error: Error, controller: ScheduledController) { this.logger.error('Cleanup job failed', error) }}The CronJob interface has three members:
| Member | Type | Required | Description |
|---|---|---|---|
schedule | readonly string | Yes | Cron expression that must match a trigger in wrangler.jsonc |
execute | (controller: ScheduledController) => Promise<void> | Yes | The work to perform when the schedule fires |
onError | (error: Error, controller: ScheduledController) => Promise<void> | No | Called when execute throws; errors here are silently caught |
The ScheduledController is the standard Cloudflare Workers type that provides scheduledTime (the timestamp of when the trigger fired) and cron (the matching cron expression).
Registering jobs
Section titled “Registering jobs”Add job classes to the jobs array in any module:
import { Module } from 'stratal/module'import { CleanupJob } from './cleanup.job'import { ReportJob } from './report.job'
@Module({ jobs: [CleanupJob, ReportJob],})export class MaintenanceModule {}Jobs are resolved from the DI container as singletons, so they can inject any service your application provides.
Multiple jobs on the same schedule
Section titled “Multiple jobs on the same schedule”You can register several jobs with the same schedule value. Stratal groups jobs by their cron expression and runs all matching jobs when the trigger fires:
@Transient()export class ExpireSessionsJob implements CronJob { readonly schedule = '0 * * * *' // Every hour
async execute(controller: ScheduledController) { // expire old sessions }}
@Transient()export class RefreshCacheJob implements CronJob { readonly schedule = '0 * * * *' // Same schedule
async execute(controller: ScheduledController) { // refresh cache entries }}Both jobs will execute whenever the 0 * * * * trigger fires.
Error handling
Section titled “Error handling”Jobs within the same schedule run sequentially. If a job’s execute method throws:
- The error is caught and stored.
- The job’s
onErrorcallback is called (if defined). IfonErroritself throws, that error is silently ignored. - Execution continues with the next job.
- After all jobs have run, if any failed, Stratal throws a
CronExecutionErrorthat aggregates every failure.
import { CronExecutionError } from 'stratal/cron'The CronExecutionError includes:
- The cron expression that triggered the run
- The number of failed jobs
- A summary string listing each failed job’s name and error message
This aggregate error is then handled by the GlobalErrorHandler, ensuring all failures are logged even if individual jobs provide their own onError handlers.
Worker setup
Section titled “Worker setup”Export a Stratal instance. The scheduled handler is built in:
import { Stratal } from 'stratal'import { AppModule } from './app.module'
export default new Stratal({ module: AppModule })When Cloudflare fires a cron trigger, Stratal.scheduled(controller) is called. It:
- Initializes the application (if not already running).
- Creates a request scope with a default
enlocale for i18n context. - Calls
cronManager.executeScheduled(controller), which finds and runs all jobs matchingcontroller.cron. - If any jobs fail, the
GlobalErrorHandlerlogs the aggregate error.