QU
queue-patterns
|
Install
mkdir -p .claude/skills/queue-patterns && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15777" && unzip -o skill.zip -d .claude/skills/queue-patterns && rm skill.zipInstalls to .claude/skills/queue-patterns
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
How the @repo/queue package works in this repo. BullMQ queue + worker pattern. Use when: adding new job types, creating handlers, enqueuing jobs, or debugging queue issues.172 chars✓ has a “when” trigger
About this skill
Queue Patterns — @repo/queue
Architecture
Any app (producer) apps/worker (consumer)
────────────────── ──────────────────────
QueueService.addJob() ──► Redis ──► WorkerService ──► handler function
- QueueService — enqueues jobs (used in any app)
- WorkerService — consumes jobs and runs handler functions (runs in
apps/worker) - Both use BullMQ under the hood and share the same Redis server + queue name
Adding a new job type
Step 1 — Define the payload type
File: packages/queue/src/types.ts
export interface JobPayloadMap {
"email.send": { to: string; subject: string; body: string }
"bulk.email.send": { to: string; subject: string; body: string }[]
// ↓ add new types here
"your.job": { yourField: string }
}
Step 2 — Add a handler
File: apps/worker/src/handlers/index.ts
export const handlers: JobHandlerMap = {
// ... existing handlers ...
"your.job": async (payload, logger) => {
// payload is strictly typed from JobPayloadMap
logger.info(`Processing ${payload.yourField}`)
}
}
TypeScript enforces that every key in JobPayloadMap has a matching handler.
Step 3 — Enqueue from any app
import { QueueService } from "@repo/queue"
const queue = new QueueService({ redis, logger })
await queue.addJob("your.job", { yourField: "value" })
// With delay:
await queue.addJob("your.job", { yourField: "value" }, { delay: 60_000 })
Key details
QueueServiceusesredis.client.duplicate()internally — the RedisClient namespace does NOT affect queue keys- BullMQ manages its own keys (e.g.
bull:default:*) — separate from the caching namespace - The worker creates its own
RedisClientbecause it's a separate process - Queue name is configurable via
QUEUE_NAMEenv var (defaults to"default") - Worker concurrency is configurable via
WORKER_CONCURRENCYenv var
Worker env
REDIS_URL=redis://localhost:6379
QUEUE_NAME=default
WORKER_CONCURRENCY=3