In modern web applications, offloading tasks to background jobs can substantially improve performance and enhance user experience. NestJS, a progressive Node.js framework, when combined with Bull (a robust Redis-based queue), provides a powerful solution for managing background jobs. This article will guide you through setting up and using Bull to manage background jobs in a NestJS application. We’ll build a simple example to illustrate the concepts.
Table of Contents
- Introduction
- Prerequisites
- Setting up NestJS Project
- Installing Required Packages
- Configuring Redis
- Creating a Bull Queue
- Creating and Processing Jobs
- Running the Application
- Conclusion
1. Introduction
Background jobs are tasks executed outside of the main user interaction flow, improving performance by allowing resource-heavy tasks to be processed asynchronously. Examples include sending emails, resizing images, or cleaning up databases. Bull provides a feature-rich library to manage these jobs with Redis as the underlying data store.
2. Prerequisites
Before diving in, ensure you have the following installed:
- Node.js (>= 12.x)
- npm (>= 6.x) or yarn
- Redis server
3. Setting up NestJS Project
First, create a new NestJS project:
$ nest new nest-bull-example
$ cd nest-bull-example
4. Installing Required Packages
Next, install @nestjs/bull
, bull
, and @nestjs/queues
:
$ npm install @nestjs/bull bull
5. Configuring Redis
Bull uses Redis to manage its job queues. Ensure Redis is running on your local machine or remote server. By default, Redis runs on port 6379. Configure it in your NestJS application.
In your app.module.ts
, import BullModule
and configure it to connect to your Redis server:
import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bull';
import { BullService } from './bull.service';
import { BullProcessor } from './bull.processor';
@Module({
imports: [
BullModule.forRoot({
redis: {
host: 'localhost', // Use your Redis server host
port: 6379,
},
}),
BullModule.registerQueue({
name: 'emailQueue',
}),
],
providers: [BullService, BullProcessor],
})
export class AppModule {}
6. Creating a Bull Queue
Create a service that will handle job creation. Create bull.service.ts
:
import { Injectable } from '@nestjs/common';
import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull';
@Injectable()
export class BullService {
constructor(
@InjectQueue('emailQueue') private readonly emailQueue: Queue,
) {}
async addEmailJob(email: string, content: string) {
await this.emailQueue.add('sendEmail', {
email,
content,
});
}
}
7. Creating and Processing Jobs
Create a processor that will handle jobs as they are added to the queue. Create bull.processor.ts
:
import { Process, Processor } from '@nestjs/bull';
import { Job } from 'bull';
@Processor('emailQueue')
export class BullProcessor {
@Process('sendEmail')
async handleSendEmailJob(job: Job) {
const { email, content } = job.data;
console.log(`Sending email to: ${email}, content: ${content}`);
// Here, you can integrate an email service to send actual emails
}
}
8. Running the Application
Now, let’s create a controller to trigger job addition. Create bull.controller.ts
:
import { Controller, Post, Body } from '@nestjs/common';
import { BullService } from './bull.service';
@Controller('email')
export class BullController {
constructor(private readonly bullService: BullService) {}
@Post()
async sendEmail(@Body() body: { email: string; content: string }) {
await this.bullService.addEmailJob(body.email, body.content);
return { message: 'Email job added to the queue' };
}
}
Finally, add this controller to your module:
import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bull';
import { BullService } from './bull.service';
import { BullProcessor } from './bull.processor';
import { BullController } from './bull.controller';
@Module({
imports: [
BullModule.forRoot({
redis: {
host: 'localhost',
port: 6379,
},
}),
BullModule.registerQueue({
name: 'emailQueue',
}),
],
providers: [BullService, BullProcessor],
controllers: [BullController],
})
export class AppModule {}
Start the application and test the API endpoint:
$ npm run start
You can use Postman or curl to POST to /email
with the following JSON body:
{
"email": "example@example.com",
"content": "Welcome to our service!"
}
Observe the console for job processing logs.
9. Conclusion
In this article, you’ve learned how to integrate Bull with NestJS to manage background jobs efficiently. This approach ensures your application remains performant and responsive by offloading resource-intensive operations to background workers. You can further extend this setup by integrating various services like email providers, image processing libraries, and more.
Happy coding! 🛠️