Skip to content

@playpals/queue ​

packages/queue

A single BullMQ queue definition, shared so the producer (api) and the consumer (ogun) cannot disagree about its name, connection, or retry policy.

The whole package ​

ts
import { Queue } from "bullmq";
import { config } from "./config";
import Redis from "ioredis";

export const PROCESS_MEDIA_QUEUE = "media-processing";

const connection = new Redis(config.redis.port, config.redis.host, {
  password: config.redis.password,
  maxRetriesPerRequest: null,
});

connection.on("error", (err) => {
  console.error("[queue] redis error", err);
});

export const ProcessMediaQueue = new Queue(PROCESS_MEDIA_QUEUE, {
  connection,
  defaultJobOptions: {
    attempts: 5,
    backoff: { type: "exponential", delay: 5000 },
    removeOnComplete: { age: 60 * 60, count: 1000 },
    removeOnFail: { age: 24 * 60 * 60 },
  },
});

That is the entire surface. Its value is not the code, it is that the queue name and retry policy exist in exactly one place.

Usage ​

Producing (apps/api/src/controllers/media.ts):

ts
import { ProcessMediaQueue } from "@playpals/queue";

await ProcessMediaQueue.add("media-processing", { mediaId: media.id });

Consuming (apps/ogun/src/index.ts):

ts
import { PROCESS_MEDIA_QUEUE } from "@playpals/queue";

new Worker(PROCESS_MEDIA_QUEUE, async (job) => processMedia(job.data.mediaId), {
  connection: redis,
  concurrency: 5,
});

Note that ogun builds its own Redis connection for the worker rather than reusing this one — a worker connection has different requirements from a producer connection.

Retry policy ​

SettingValueMeaning
attempts3Total tries per job
backoff.typeexponential2 s, 4 s, 8 s
backoff.delay2000Base delay in ms

After the third failure the job moves to the failed set and stays there for inspection.

maxRetriesPerRequest: null ​

BullMQ requires this on its ioredis connections. Without it, ioredis gives up on a command after a few retries and BullMQ's blocking operations break in ways that are hard to diagnose. Do not remove it.

Configuration ​

VariableDefaultNotes
REDIS_HOSTlocalhost
REDIS_PORT6379
REDIS_PASSWORD—The local Compose Redis uses playpalz
REDIS_URL—Present in .env.example; the queue itself uses host/port/password

Adding a queue ​

  1. Export a new name constant and Queue instance from packages/queue/src/index.ts.
  2. Add a Worker for it — in ogun if it is media-shaped, otherwise in a new service.
  3. Rebuild the package so both sides pick up the export.

Keep the name constant in this package. A hard-coded queue string in two repositories' worth of services is exactly the bug this package exists to prevent.

Internal documentation — PlayPalz platform