A queue producer sends messages or tasks to a queue so other parts of the app can process them later. It helps keep things organized and smooth.
Queue producers in NestJS
import { Injectable } from '@nestjs/common'; import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; @Injectable() export class MyProducerService { constructor(@InjectQueue('myQueue') private readonly myQueue: Queue) {} async sendMessage(data: any) { await this.myQueue.add(data); } }
Use @InjectQueue('queueName') to get the queue instance.
Use queue.add(data) to send a message to the queue.
import { Injectable } from '@nestjs/common'; import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; @Injectable() export class EmptyDataProducer { constructor(@InjectQueue('emptyQueue') private readonly emptyQueue: Queue) {} async sendEmpty() { await this.emptyQueue.add({}); } }
import { Injectable } from '@nestjs/common'; import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; @Injectable() export class SingleItemProducer { constructor(@InjectQueue('singleItemQueue') private readonly singleItemQueue: Queue) {} async sendSingleItem() { await this.singleItemQueue.add({ task: 'sendEmail', to: 'user@example.com' }); } }
import { Injectable } from '@nestjs/common'; import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; @Injectable() export class MultipleItemsProducer { constructor(@InjectQueue('multiQueue') private readonly multiQueue: Queue) {} async sendMultiple() { await this.multiQueue.add({ task: 'generateReport', reportId: 123 }); await this.multiQueue.add({ task: 'cleanup', olderThanDays: 30 }); } }
This NestJS module sets up a queue named 'tasks' connected to Redis. The QueueProducerService sends a task message when the app starts.
import { Module, Injectable, OnModuleInit } from '@nestjs/common'; import { BullModule, InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; @Injectable() export class QueueProducerService implements OnModuleInit { constructor(@InjectQueue('tasks') private readonly tasksQueue: Queue) {} async onModuleInit() { console.log('Sending initial task to queue...'); await this.sendTask({ type: 'email', to: 'friend@example.com', subject: 'Hello!' }); console.log('Task sent.'); } async sendTask(data: any) { await this.tasksQueue.add(data); } } @Module({ imports: [ BullModule.forRoot({ redis: { host: 'localhost', port: 6379 }, }), BullModule.registerQueue({ name: 'tasks' }), ], providers: [QueueProducerService], }) export class AppModule {} // To run this example, start a Redis server locally. // Then start NestJS app. It will send a task to the 'tasks' queue on startup.
Adding a job to the queue is usually fast and non-blocking.
Make sure Redis is running and accessible for Bull queues to work.
Common mistake: forgetting to register the queue in the module imports.
Queue producers send tasks or messages to queues for later processing.
Use @InjectQueue to get the queue and queue.add() to send data.
This helps keep your app responsive and organized by handling work asynchronously.
Practice
Solution
Step 1: Understand the role of queue producer
A queue producer is responsible for sending tasks or messages to a queue, not processing them.Step 2: Differentiate producer from consumer
Consumers process tasks, while producers only add tasks to the queue.Final Answer:
To send tasks or messages to a queue for later processing -> Option DQuick Check:
Queue producer = sends tasks [OK]
- Confusing producer with consumer
- Thinking producer processes tasks
- Assuming producer deletes tasks
Solution
Step 1: Recall correct syntax for @InjectQueue
The decorator requires the queue name as a string and the property must be typed as Queue.Step 2: Check property declaration
It should be private readonly with type Queue, no manual instantiation needed.Final Answer:
@InjectQueue('email') private readonly emailQueue: Queue; -> Option CQuick Check:
@InjectQueue('name') private readonly queue: Queue [OK]
- Missing private or readonly keywords
- Trying to instantiate Queue manually
- Incorrect decorator usage without queue name
sendEmail() is called?async sendEmail() {
await this.emailQueue.add('send_email', { to: 'user@example.com' });
return 'Email task added';
}Solution
Step 1: Understand queue.add() behavior
The add() method adds a job to the queue asynchronously but does not send the email immediately.Step 2: Check return value of sendEmail()
After adding the job, the function returns the string 'Email task added'.Final Answer:
'Email task added' -> Option BQuick Check:
queue.add() adds job, function returns confirmation [OK]
- Assuming add() sends email immediately
- Thinking add() returns error for job name
- Ignoring async nature of add()
@Injectable()
export class NotificationProducer {
constructor(@InjectQueue('notifications') private notificationsQueue: Queue) {}
async sendNotification(data: any) {
this.notificationsQueue.add('notify', data);
}
}Solution
Step 1: Check async method usage
The add() method returns a promise, so it should be awaited inside an async function to handle completion properly.Step 2: Verify other parts
The queue name and access modifiers are correct; async keyword is appropriate.Final Answer:
Missing await before this.notificationsQueue.add() -> Option AQuick Check:
Async add() needs await to handle promise [OK]
- Forgetting await on async queue.add()
- Changing queue name incorrectly
- Removing async keyword unnecessarily
Solution
Step 1: Understand job priority in queues
Queue jobs can have individual priorities set when added, using options like { priority: number }.Step 2: Evaluate options
Creating multiple queues or setting priority globally is not the recommended way; manual sorting is inefficient.Final Answer:
Use queue.add(jobName, data, { priority: number }) to set priority per job -> Option AQuick Check:
Set priority per job with add() options [OK]
- Trying to set priority globally on queue
- Creating many queues instead of one
- Ignoring built-in priority support
Ready to prove it?
Pass the test and this pattern moves unknown
