Avleon's queue is built on BullMQ, which runs on
Redis. Both are optional peer dependencies:
npm i bullmq ioredis
There are two ways to work with jobs: a queue class, which both produces and
consumes jobs, and a worker class, which only consumes a queue someone else
fills.
Extend AvleonQueue<T> and decorate it with @Queue. T is the shape of the
job payload.
queues/email.queue.ts
import { AvleonQueue, Queue, JobHandler, Job } from '@avleon/core';
export type EmailPayload = {
to: string;
subject: string;
};
@Queue({
name: 'email',
adapter: { connection: { host: '127.0.0.1', port: 6379 } },
})
export class EmailQueue extends AvleonQueue<EmailPayload> {
@JobHandler('welcome')
async sendWelcome(job: Job<EmailPayload>) {
console.log(`Sending welcome mail to ${job.data.to}`);
}
@JobHandler('reset-password')
async sendReset(job: Job<EmailPayload>) {
console.log(`Sending reset mail to ${job.data.to}`);
}
}
Each @JobHandler('name') handles jobs added under that name. For jobs added
without a name — or with a name no handler matches — define a handler method
on the class, or pass handler in the decorator config.
import { AppService } from '@avleon/core';
import { EmailQueue } from '../queues/email.queue';
@AppService
export class SignupService {
constructor(private readonly emailQueue: EmailQueue) {}
async register(email: string) {
await this.emailQueue.add('welcome', {
to: email,
subject: 'Welcome aboard',
});
}
}
Other producer methods:
// run 30 seconds from now
await emailQueue.delay('welcome', { to, subject }, 30_000);
// add with any BullMQ job option
await emailQueue.add('welcome', { to, subject }, { attempts: 3, backoff: 1000 });
// inspect and control
const job = await emailQueue.getJob(jobId);
await emailQueue.pause();
await emailQueue.resume();
When the producer lives elsewhere, extend AvleonWorkerBase<T> and point
@AvleonWorker at the queue name. Implement process; the lifecycle hooks are
optional.