How to Schedule Tasks in NestJS

Updated: December 31, 2023 By: Guest Contributor Post a comment

Introduction

Scheduling tasks in applications can be an integral part of software engineering, allowing for various operations like database cleanup, sending batch emails, or periodic data aggregation to occur automatically. In this tutorial, we’ll explore how to schedule tasks in NestJS, leveraging the latest syntax of TypeScript to ensure your operations are both efficient and reliable.

Setting up NestJS

To begin with, make sure you have Node.js installed and then install NestJS CLI by running:

npm i -g @nestjs/cli

Create a new NestJS project by executing:

nest new task-scheduler-app

Navigate into the project directory:

cd task-scheduler-app

We’ll also need to install the @nestjs/schedule module:

npm install @nestjs/schedule

Basic Scheduling

To integrate basic task scheduling in your NestJS app, let’s start with simple timed tasks. First, import the ScheduleModule into your app.module.ts:

import { ScheduleModule } from '@nestjs/schedule';

@Module({
  imports: [
    ScheduleModule.forRoot()
  ],
  //... other configurations
})
export class AppModule {}

Now, let’s create our first scheduled task. Inside any service, use the @Cron decorator to define a task that runs at a specific time:

import { Injectable } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';

@Injectable()
export class TasksService {

  @Cron('45 * * * * *')
  handleCron() {
    console.log('Cron task running every minute at 45 seconds');
  }
}

The above Cron expression means the ‘handleCron’ will execute every minute when the second hand is at 45. Let’s move into more nuanced scheduling.

Interval Timed Tasks

Using the @Interval decorator, tasks can be executed at recurring time intervals. Here’s how you can schedule a task to run every 5 seconds:

import { Interval } from '@nestjs/schedule';

  // inside the TasksService class
  @Interval(5000)
  handleInterval() {
    console.log('Interval task running every 5 seconds');
  }

This is useful for operations where exact timing isn’t critical, but regular occurrence is.

Timeout Tasks

Sometimes you want to execute a task just once, after a delay. The @Timeout decorator is perfect for this:

import { Timeout } from '@nestjs/schedule';

  // inside the TasksService class
  @Timeout(10000)
  handleTimeout() {
    console.log('Timeout task running once after 10 seconds');
  }

The ‘handleTimeout’ function will be executed once, 10 seconds after the application starts.

Advanced Scheduling

For more advanced requirements, we can use the CronExpression enum to represent commonly used cron schedules or create a more specific custom cron pattern:

import { Cron, CronExpression } from '@nestjs/schedule';

  // inside the TasksService class
  @Cron(CronExpression.EVERY_DAY_AT_NOON)
  handleCronExpression() {
    console.log('Scheduled task running every day at noon');
  }

  @Cron('0 30 11 * * 5')
  handleCustomCron() {
    console.log('Custom cron task running at 11:30 AM every Friday');
  }

When the pre-defined expressions are insufficient, custom cron strings allow for complete flexibility.

Dynamic Scheduling

For situations requiring dynamic schedule creation and cancellation, we’ll use the SchedulerRegistry:

import { Injectable } from '@nestjs/common';
import { SchedulerRegistry } from '@nestjs/schedule';

@Injectable()
export class TasksService {

  constructor(private schedulerRegistry: SchedulerRegistry) {}

  addDynamicCronJob(name: string, seconds: string) {
    const job = new CronJob(`${seconds} * * * * *`, () => {
      console.log(`Dynamic job ${name} executed`);
    });

    this.schedulerRegistry.addCronJob(name, job);
    job.start();
  }

  deleteCronJob(name: string) {
    this.schedulerRegistry.deleteCronJob(name);
    console.log(`Dynamic job ${name} deleted`);
  }
}

Here we’ve made a service capable of adding and deleting jobs dynamically during runtime based on your application’s needs.

Cron Job Options

NestJS also provides options for more granulated control over the cron jobs like setting time zones or starting and stopping jobs manually:

const job = new CronJob('0 * * * *', () => {
  // task to perform
}, {
  timeZone: 'America/Los_Angeles'
});

This is especially important when coordinating tasks across different geographical regions.

Conclusion

Whether you’re scheduling simple timed tasks, intervals, or managing dynamic schedules, NestJS with the @nestjs/schedule module is a powerful and intuitive framework for Node.js that simplifies these operations. Remember that reliable task scheduling is vital for ensuring the timely and efficient execution of background tasks in your applications. As promised, we’ve covered scheduling from basic to advanced, giving you the tools to start implementing your automation with ease.