Task scheduling
Task scheduling allows you to schedule arbitrary code (methods/functions) to execute at a fixed date/time, at recurring intervals, or once after a specified interval. In the Linux world, this is often handled by packages like cron at the OS level. For Node.js apps, there are several packages that emulate cron-like functionality. Nest provides the @nestjs/schedule package, which integrates with the popular Node.js cron package. We'll cover this package in the current chapter.
Installation
To begin using it, we first install the required dependencies.
To activate job scheduling, import the ScheduleModule into the root AppModule and run the forRoot() static method as shown below:
The .forRoot() call initializes the scheduler and registers any declarative cron jobs, timeouts and intervals that exist within your app. Registration occurs when the onApplicationBootstrap lifecycle hook occurs, ensuring that all modules have loaded and declared any scheduled jobs.
Declarative cron jobs
A cron job schedules an arbitrary function (method call) to run automatically. Cron jobs can run:
- Once, at a specified date/time.
- On a recurring basis; recurring jobs can run at a specified instant within a specified interval (for example, once per hour, once per week, once every 5 minutes)
Declare a cron job with the @Cron() decorator preceding the method definition containing the code to be executed, as follows:
In this example, the handleCron() method will be called each time the current second is 45. In other words, the method will be run once per minute, at the 45 second mark.
The @Cron() decorator supports the following standard cron patterns:
- Asterisk (e.g.
*) - Ranges (e.g.
1-3,5) - Steps (e.g.
*/2)
In the example above, we passed 45 * * * * * to the decorator. The following key shows how each position in the cron pattern string is interpreted:
Some sample cron patterns are:
The @nestjs/schedule package provides a convenient enum with commonly used cron patterns. You can use this enum as follows:
In this example, the handleCron() method will be called every 30 seconds. If an exception occurs, it will be logged to the console, as every method annotated with @Cron() is automatically wrapped in a try-catch block.
Alternatively, you can supply a JavaScript Date object to the @Cron() decorator. Doing so causes the job to execute exactly once, at the specified date.
info Hint Use JavaScript date arithmetic to schedule jobs relative to the current date. For example,
@Cron(new Date(Date.now() + 10 * 1000))to schedule a job to run 10 seconds after the app starts.
Also, you can supply additional options as the second parameter to the @Cron() decorator.
You can access and control a cron job after it's been declared, or dynamically create a cron job (where its cron pattern is defined at runtime) with the Dynamic API. To access a declarative cron job via the API, you must associate the job with a name by passing the name property in an optional options object as the second argument of the decorator.
Declarative intervals
To declare that a method should run at a (recurring) specified interval, prefix the method definition with the @Interval() decorator. Pass the interval value, as a number in milliseconds, to the decorator as shown below:
info Hint This mechanism uses the JavaScript
setInterval()function under the hood. You can also utilize a cron job to schedule recurring jobs.
If you want to control your declarative interval from outside the declaring class via the Dynamic API, associate the interval with a name using the following construction:
If an exception occurs, it will be logged to the console, as every method annotated with @Interval() is automatically wrapped in a try-catch block.
The Dynamic API also enables creating dynamic intervals, where the interval's properties are defined at runtime, and listing and deleting them.
Declarative timeouts
To declare that a method should run (once) at a specified timeout, prefix the method definition with the @Timeout() decorator. Pass the relative time offset (in milliseconds), from application startup, to the decorator as shown below:
info Hint This mechanism uses the JavaScript
setTimeout()function under the hood.
If an exception occurs, it will be logged to the console, as every method annotated with @Timeout() is automatically wrapped in a try-catch block.
If you want to control your declarative timeout from outside the declaring class via the Dynamic API, associate the timeout with a name using the following construction:
The Dynamic API also enables creating dynamic timeouts, where the timeout's properties are defined at runtime, and listing and deleting them.
Dynamic schedule module API
The @nestjs/schedule module provides a dynamic API that enables managing declarative cron jobs, timeouts and intervals. The API also enables creating and managing dynamic cron jobs, timeouts and intervals, where the properties are defined at runtime.
Dynamic cron jobs
Obtain a reference to a CronJob instance by name from anywhere in your code using the SchedulerRegistry API. First, inject SchedulerRegistry using standard constructor injection:
info Hint Import the
SchedulerRegistryfrom the@nestjs/schedulepackage.
Then use it in a class as follows. Assume a cron job was created with the following declaration:
Access this job using the following:
The getCronJob() method returns the named cron job. The returned CronJob object has the following methods:
stop()- stops a job that is scheduled to run.start()- restarts a job that has been stopped.setTime(time: CronTime)- stops a job, sets a new time for it, and then starts itlastDate()- returns aDateTimerepresentation of the date on which the last execution of a job occurred.nextDate()- returns aDateTimerepresentation of the date when the next execution of a job is scheduled.nextDates(count: number)- Provides an array (sizecount) ofDateTimerepresentations for the next set of dates that will trigger job execution.countdefaults to 0, returning an empty array.
info Hint Use
toJSDate()onDateTimeobjects to render them as a JavaScript Date equivalent to this DateTime.
Create a new cron job dynamically using the SchedulerRegistry#addCronJob method, as follows:
In this code, we use the CronJob object from the cron package to create the cron job. The CronJob constructor takes a cron pattern (just like the @Cron() decorator) as its first argument, and a callback to be executed when the cron timer fires as its second argument. The SchedulerRegistry#addCronJob method takes two arguments: a name for the CronJob, and the CronJob object itself.
warning Warning Remember to inject the
SchedulerRegistrybefore accessing it. ImportCronJobfrom thecronpackage.
Delete a named cron job using the SchedulerRegistry#deleteCronJob method, as follows:
List all cron jobs using the SchedulerRegistry#getCronJobs method as follows:
The getCronJobs() method returns a map. In this code, we iterate over the map and attempt to access the nextDate() method of each CronJob. In the CronJob API, if a job has already fired and has no future firing date, it throws an exception.
Dynamic intervals
Obtain a reference to an interval with the SchedulerRegistry#getInterval method. As above, inject SchedulerRegistry using standard constructor injection:
And use it as follows:
Create a new interval dynamically using the SchedulerRegistry#addInterval method, as follows:
In this code, we create a standard JavaScript interval, then pass it to the SchedulerRegistry#addInterval method.
That method takes two arguments: a name for the interval, and the interval itself.
Delete a named interval using the SchedulerRegistry#deleteInterval method, as follows:
List all intervals using the SchedulerRegistry#getIntervals method as follows:
Dynamic timeouts
Obtain a reference to a timeout with the SchedulerRegistry#getTimeout method. As above, inject SchedulerRegistry using standard constructor injection:
And use it as follows:
Create a new timeout dynamically using the SchedulerRegistry#addTimeout method, as follows:
In this code, we create a standard JavaScript timeout, then pass it to the SchedulerRegistry#addTimeout method.
That method takes two arguments: a name for the timeout, and the timeout itself.
Delete a named timeout using the SchedulerRegistry#deleteTimeout method, as follows:
List all timeouts using the SchedulerRegistry#getTimeouts method as follows:
Example
A working example is available here.

