BullModule.forRoot({ connection: { host: "localhost", port: 6379 } });
BullModule.registerQueue({ name: "email" });
constructor(@InjectQueue("email") private queue: Queue) {}
await this.queue.add("welcome", { userId }, { attempts: 3, backoff: { type: "exponential", delay: 1000 } });
@Processor("email")
export class EmailConsumer extends WorkerHost {
async process(job: Job<{ userId: number }>) {
if (job.name === "welcome") await this.mail.sendWelcome(job.data.userId);
}
}
Use @nestjs/bullmq. The API adds a job to a queue, and a separate worker class processes it. BullMQ stores the jobs in Redis.
Setup. BullModule.forRoot() sets the Redis connection. BullModule.registerQueue() registers a named queue.
The producer adds jobs. It injects the queue with @InjectQueue("email") and calls queue.add(name, data, options). Useful options:
attemptsandbackofffor retriesdelayfor schedulingremoveOnCompletefor cleanup
The HTTP request returns as soon as the job is stored. The user doesn't wait for the email.
The consumer runs jobs. It is a class decorated with @Processor("email"). It extends WorkerHost and implements process(job). You must register it as a provider. @OnWorkerEvent("completed") or @OnWorkerEvent("failed") lets you react to job events.
Workers can run in the same app or in separate processes. So slow work can scale separately from the API.
- Set up with
BullModule.forRootandregisterQueue. - The producer uses
@InjectQueueandqueue.add, with retry options. - The consumer is a
@Processorclass that extendsWorkerHost. - Jobs are stored in Redis, so the request returns immediately.
- Workers can scale separately from the API.
- Queues (https://docs.nestjs.com/techniques/queues)docs.nestjs.com