Queue consumers (processors) help your app handle tasks one by one or in groups without blocking other work. They listen to a queue and process jobs as they come.
Queue consumers (processors) in NestJS
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('queueName') export class QueueConsumer { @Process('jobName') async handleJob(job: Job<any>) { // Your job processing logic here } }
@Processor decorator marks the class as a queue consumer for a specific queue.
@Process decorator marks the method that will handle jobs with a specific name.
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('emailQueue') export class EmailConsumer { @Process('sendEmail') async sendEmailJob(job: Job<{ to: string; subject: string }>) { console.log(`Sending email to ${job.data.to} with subject ${job.data.subject}`); } }
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('imageQueue') export class ImageConsumer { @Process('resizeImage') async resizeImageJob(job: Job<{ imagePath: string }>) { if (!job.data.imagePath) { console.log('No image path provided'); return; } console.log(`Resizing image at ${job.data.imagePath}`); } }
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('emptyQueue') export class EmptyConsumer { @Process('noJob') async noJobHandler(job: Job) { console.log('This will never run because no jobs are added'); } }
This NestJS app sets up a queue named 'taskQueue' and a consumer that processes 'printTask' jobs. It adds one job with a message, which the consumer prints.
import { Injectable, Module } from '@nestjs/common'; import { BullModule } from '@nestjs/bull'; import { InjectQueue, Processor, Process } from '@nestjs/bull'; import { Job, Queue } from 'bull'; import { NestFactory } from '@nestjs/core'; @Processor('taskQueue') export class TaskConsumer { @Process('printTask') async handlePrintTask(job: Job<{ message: string }>) { console.log(`Processing task: ${job.data.message}`); } } @Module({ imports: [ BullModule.forRoot({ redis: { host: 'localhost', port: 6379 } }), BullModule.registerQueue({ name: 'taskQueue' }), ], providers: [TaskConsumer, JobProducer], }) export class AppModule {} @Injectable() class JobProducer { constructor(@InjectQueue('taskQueue') private taskQueue: Queue) {} async addJob() { await this.taskQueue.add('printTask', { message: 'Hello from queue!' }); console.log('Job added to queue'); } } async function bootstrap() { const app = await NestFactory.createApplicationContext(AppModule); const producer = app.get(JobProducer); await producer.addJob(); setTimeout(() => app.close(), 2000); } bootstrap();
Processing a job usually takes O(1) time per job, but depends on job complexity.
Memory use depends on job data size and number of concurrent jobs.
Common mistake: forgetting to register the queue or consumer in the module.
Use queue consumers when tasks can be done later without blocking user actions.
Queue consumers listen to queues and process jobs asynchronously.
Use @Processor to mark a consumer class and @Process to mark job handlers.
This helps keep your app responsive by handling tasks in the background.
Practice
Solution
Step 1: Understand the role of queue consumers
Queue consumers listen to queues and handle jobs asynchronously, allowing background processing.Step 2: Compare with other options
Sending HTTP requests, rendering UI, and managing migrations are unrelated to queue consumers.Final Answer:
To listen to a queue and process jobs asynchronously in the background -> Option CQuick Check:
Queue consumer = background job handler [OK]
- Confusing queue consumers with HTTP controllers
- Thinking queue consumers run synchronously
- Assuming queue consumers manage UI rendering
Solution
Step 1: Identify the decorator for queue consumers
The @Processor decorator marks a class as a queue consumer in NestJS.Step 2: Differentiate from other decorators
@Process marks methods, @Queue and @Consumer are not valid NestJS decorators for this purpose.Final Answer:
@Processor -> Option AQuick Check:
Class decorator for consumers = @Processor [OK]
- Using @Process on the class instead of methods
- Confusing @Processor with @Queue
- Assuming @Consumer is a valid decorator
import { Processor, Process } from '@nestjs/bull';
import { Job } from 'bull';
@Processor('email')
export class EmailProcessor {
@Process('send')
async handleSend(job: Job) {
console.log(`Sending email to ${job.data.name}`);
}
}Solution
Step 1: Understand job data usage
The job object contains data with a name property 'Alice'. The method logs this value.Step 2: Confirm method is called on 'send' jobs
The @Process('send') decorator ensures handleSend runs for jobs named 'send' in the 'email' queue.Final Answer:
Sending email to Alice -> Option BQuick Check:
job.data.name = 'Alice' logged correctly [OK]
- Assuming job.data is undefined
- Thinking method won't run without explicit call
- Confusing queue name with job name
import { Processor, Process } from '@nestjs/bull';
import { Job } from 'bull';
@Processor('notifications')
export class NotificationProcessor {
@Process()
async handleNotification(job: Job) {
console.log('Notification:', job.data.message);
}
}Solution
Step 1: Check @Process decorator usage
@Process requires a job name string to specify which jobs to handle; it's missing here.Step 2: Validate other parts
@Processor on class is correct, Job type is valid, console.log syntax is correct.Final Answer:
@Process decorator is missing the job name argument -> Option DQuick Check:
@Process needs job name argument [OK]
- Omitting job name in @Process decorator
- Removing @Processor from class
- Changing Job type unnecessarily
Solution
Step 1: Understand queue and job type separation
The queue is 'notifications'. The job types are 'email' and 'sms'. One class can handle multiple job types with separate @Process decorators.Step 2: Validate correct decorator usage
@Processor('notifications') marks the queue. Methods use @Process('email') and @Process('sms') to handle each job type.Final Answer:
Use @Processor('notifications') on class, and two methods with @Process('email') and @Process('sms') decorators -> Option AQuick Check:
One class, multiple @Process methods for job types [OK]
- Creating multiple classes for same queue unnecessarily
- Using multiple @Processor decorators on one class
- Omitting @Processor on class and only using @Process
Ready to prove it?
Pass the test and this pattern moves unknown
