SDK Reference

The @bullrun/sdk package provides everything you need to define, trigger, and manage background jobs.

defineTask()

Define a background task with a handler function. Tasks are the core unit of work in BullRun.

import { defineTask } from "@bullrun/sdk";

export const processOrder = defineTask({
  name: "process-order",      // Unique task name
  queue: "orders",             // Optional queue (default: "default")
  concurrency: 10,             // Max concurrent executions
  timeout: 30_000,             // Timeout in ms
  retry: {
    attempts: 5,
    backoff: { type: "exponential", delay: 2000 },
  },
  middleware: [withLogging],   // Optional middleware chain
  handler: async (payload: { orderId: string }) => {
    const order = await db.getOrder(payload.orderId);
    await fulfillOrder(order);
    return { fulfilled: true };
  },
});

defineQueue()

import { defineQueue } from "@bullrun/sdk";

export const emailQueue = defineQueue({
  name: "emails",
  concurrency: 20,
});

BullRun Client

The client is used to trigger tasks and check job status from your application code.

import { BullRun } from "@bullrun/sdk";

const client = new BullRun({
  apiKey: process.env.BULLRUN_API_KEY!,
  baseUrl: "https://api.bullrun.dev", // optional, this is the default
});

// Trigger a task
const result = await client.trigger("process-order", { orderId: "123" });

// Trigger with delay (5 minutes)
await client.trigger("send-reminder", { userId: "456" }, { delay: 300_000 });

// Check job status
const status = await client.getJobStatus(result.data.jobId);

// Schedule a recurring task
await client.schedule("daily-report", "0 9 * * *", {}, {
  timezone: "America/New_York",
  name: "morning-report",
});

Middleware

Middleware wraps task handlers with reusable logic. BullRun includes built-in middleware and supports custom middleware.

import {
  createMiddleware,
  withLogging,
  withTimeout,
  withRetry,
} from "@bullrun/sdk";

// Built-in middleware
const myTask = defineTask({
  name: "my-task",
  middleware: [
    withLogging,              // Log start/finish with duration
    withTimeout(30_000),      // 30s timeout
    withRetry(2, 1000),       // 2 extra retries with 1s backoff
  ],
  handler: async (payload) => { ... },
});

// Custom middleware
const withAuth = createMiddleware(async (ctx, next) => {
  const user = await validateToken(ctx.payload.token);
  if (!user) throw new Error("Unauthorized");
  return next();
});

triggerAndWait()

Trigger a task and wait for it to complete. Polls the status endpoint until the job reaches a terminal state.

const result = await client.triggerAndWait("process-data", { items: ["a", "b"] });
if (result.ok) {
  console.log(result.output); // typed result
}
// Or throw on failure:
const output = result.unwrap();

Batch Operations

Run multiple tasks in parallel and wait for all to complete.

const results = await client.batch.triggerByTaskAndWait([
  { task: "enrich-traffic", payload: {} },
  { task: "enrich-demographics", payload: {} },
]);
for (const run of results.runs) {
  if (run.ok) console.log(run.output);
  else console.error(run.error);
}

schedules.task()

Define a cron-scheduled task. Compatible with Trigger.dev's scheduling pattern.

import { schedules } from "@bullrun/sdk";

export const dailyPipeline = schedules.task({
  id: "cre/daily-pipeline",
  cron: "0 6 * * *",
  timezone: "UTC",
  retry: { maxAttempts: 2 },
  run: async () => {
    // runs daily at 6am UTC
  },
});

Logger

Structured logging that flows to the BullRun dashboard. Drop-in replacement for @trigger.dev/sdk logger.

import { logger } from "@bullrun/sdk";

logger.info("Processing started", { count: 42 });
logger.warn("Rate limit approaching");
logger.error("Failed to fetch", { url, status: 429 });
logger.debug("Raw response", { body });

Logs are buffered and flushed to the API in batches. Visible in the job detail panel.

Worker Runtime

Start BullMQ workers that execute your registered tasks.

import { taskRegistry, startWorkers, stopWorkers } from "@bullrun/sdk";
taskRegistry.activate();
await import("./tasks/my-task.js");

const workers = await startWorkers({
  connection: redis,
  projectId: "my-project",
  apiUrl: "https://api.bullrun.dev",
  apiKey: "br_...",
});

// Graceful shutdown
process.on("SIGTERM", () => stopWorkers(workers));