Sling Academy
Home/Node.js/How to Schedule Tasks in NestJS

How to Schedule Tasks in NestJS

Last updated: December 31, 2023

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.

Next Article: How to Validate Data in NestJS

Previous Article: How to Implement Caching in NestJS

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates