@tulipes/bullmq
v0.1.1
Published
BullMQ queues provider for Tulipes apps: producers in every process, consumers in the worker, behind core's queues capability
Maintainers
Readme
@tulipes/bullmq
The BullMQ queues provider for Tulipes
apps. Every module's queues/*.queues.ts runs in every process: producers exist
everywhere, processors are registered everywhere, and the worker process turns
them into consumers. Core itself no longer installs BullMQ or ioredis; an app
without background work declares no provider and never pays for one.
Requires Node 24.x and a core that ships the provider contract with serve/drain
hooks. bullmq and ioredis are this package's own dependencies — the app never
imports BullMQ, and the provider's connections are never shared with the app's
own Redis clients.
Select it
{ "tulipes": { "providers": { "queues": "@tulipes/bullmq" } } }plus REDIS_URL declared by the app's sys core module and set. A queues/
directory requires the provider automatically; a module that only produces
declares "tulipes": { "requires": ["queues"] }. Installing this package
without the declaration selects nothing; a REDIS_URL on its own starts nothing.
Use it
// modules/billing/queues/invoices.queues.ts
import type { Ctx } from "@tulipes/core/boot";
import type { QueueRegistry } from "@tulipes/bullmq";
export default function invoiceQueues(ctx: Ctx, queues: QueueRegistry): void {
queues.define("billing.send-invoice");
queues.process("billing.send-invoice", async (job) => ({ sent: true }));
}
// anywhere after acquisition
await requireQueues(ctx).add("billing.send-invoice", "send", { invoiceId });Behavior
- One ioredis connection per queue and one blocking connection per worker,
maxRetriesPerRequest: null; owned by core before the first queue file runs. - Worker mode:
serve()starts oneWorkerper registered processor; core refuses a worker that serves nothing. - Shutdown:
drain()closes workers (finishing active jobs) concurrently with the HTTP drain and moduleonDrainhooks while producers stay usable — a module'sonShutdownmay still enqueue; then queues and connections close in reverse provider order, with forceddisconnect()under the shared deadline. - Queue names use
.; duplicates and processors for undefined queues are aggregate boot errors naming the modules.
Versions
0.1.0-rc.1 requires core ^0.10.0-rc.2, the candidate that added the serve/drain
hooks; install both with @next. See core's
MIGRATING.md.
