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));