Semola

Queue

Redis-backed background jobs with retries and concurrency

Run work in the background with Redis. Jobs are JSON-serialized, polled by workers, and retried with backoff when they fail.

import { Queue } from "semola/queue";

Needs a Bun.RedisClient.

Basic usage

type EmailJob = {
  to: string;
  subject: string;
};

const emails = new Queue<EmailJob>({
  name: "emails",
  redis: redisClient,
  concurrency: 4,
  retries: 3,
  handler: async (data, signal) => {
    await sendEmail(data.to, data.subject);
  },
});

const jobId = await emails.enqueue({
  to: "user@example.com",
  subject: "Welcome",
});

// later, when shutting down:
await emails.stop();

Workers start as soon as you construct the queue. enqueue returns a job id. Failed jobs retry until retries is exhausted, then land on a dead-letter list (queue:{name}:dead-letter).

Options

OptionDefaultMeaning
namerequiredRedis key namespace
redisrequiredBun.RedisClient
handlerrequired(data, signal?) => void | Promise<void>
retries3Max attempts after the first failure
retryBackoffbaseDelay 1s, multiplier 2, maxDelay 60sExponential backoff
timeout30000Per-job timeout in ms
concurrency1Parallel workers
pollInterval100Idle poll delay in ms
onSuccess-After a successful job
onRetry-Before a retry
onError-When retries are exhausted
onParseError-When a Redis payload cannot be parsed

Use signal in the handler to abort work when the job times out.

Shutdown

await emails.stop();

Stops polling and waits for in-flight handlers to finish.

On this page