@samveys/queue

Job, retry, driver database dengan SKIP LOCKED, outbox transaksional, worker

Versi
1.0.35 Nov 2026
Pasang
pnpm add @samveys/queue
Dokumentasi
README paket ini

Daftar ini dibaca dari versi 1.0.2; jalankan pnpm sync untuk memperbaruinya.

Import
import { createQueue, createQueueCommands, createQueueTables, databaseQueueDriver, defineJob, fake, … } from '@samveys/queue'

Fungsi (8)

createQueue Fungsi

Builds a queue over a driver. The worker loop lives here; drivers only store rows.

function createQueue(options: QueueOptions): Queue;

Diekspor dari packages/queue/src/queue.ts

createQueueCommands Fungsi

The queue commands. `resolve` returns the queue bound in the app's container.

function createQueueCommands(resolve: (app: AppContext) => Queue): readonly QueueCommand[];

Diekspor dari packages/queue/src/commands.ts

createQueueTables Fungsi

Creates the queue tables if they do not exist yet. Run it from a migration or at deploy time.

function createQueueTables(db: Database, jobs?: string, failed?: string): Promise<void>;

Diekspor dari packages/queue/src/database-driver.ts

databaseQueueDriver Fungsi

The `database` queue driver. Reservation is race-free without an external lock: - PostgreSQL / MySQL / MariaDB: `SELECT … FOR UPDATE SKIP LOCKED` then `UPDATE`, in one transaction; - SQLite: one atomic `UPDATE … WHERE id = (SELECT … LIMIT 1) … RETURNING *`. Reserving counts an attempt, so a job whose worker crashed cannot loop forever.

function databaseQueueDriver(options: DatabaseDriverOptions): QueueDriver;

Diekspor dari packages/queue/src/database-driver.ts

defineJob Fungsi

Defines a job: a named handler with a retry policy.

function defineJob<P>(input: JobInput<P>): Job<P>;

Diekspor dari packages/queue/src/job.ts

fake Fungsi

A queue that records dispatches and runs nothing. Use it in tests: `queue.assertDispatched(job)`.

function fake(): FakeQueue;

Diekspor dari packages/queue/src/fake.ts

queue Fungsi

The `@samveys/queue` plugin: binds `'queue'` and adds `queue:work`, `queue:failed` and `queue:retry`.

function queue(config?: QueueConfig): import("@samveys/core").Plugin<QueueConfig>;

Diekspor dari packages/queue/src/plugin.ts

queueTablesSql Fungsi

DDL for the two queue tables on the database's dialect.

function queueTablesSql(db: Pick<Database, 'dialect'>, jobs?: string, failed?: string): readonly string[];

Diekspor dari packages/queue/src/database-driver.ts

Nilai (1)

DEFAULT_QUEUE Nilai

Default queue name used when a job or dispatch does not name one.

const DEFAULT_QUEUE = "default";

Diekspor dari packages/queue/src/contracts.ts

Interface (17)

DatabaseDriverOptions Interface

Tidak ada komentar dokumentasi.

interface DatabaseDriverOptions {
    /** Resolves the database lazily, so the driver can be configured before the database plugin boots. */
    readonly database: () => Database;

Diekspor dari packages/queue/src/database-driver.ts

DispatchOptions Interface

Tidak ada komentar dokumentasi.

interface DispatchOptions {
    /** Do not make the job available before now + delayMs. */
    readonly delayMs?: number;
    /** Target queue; defaults to the job's queue. */
    readonly queue?: string;
    /**
     * Write the job row inside this database transaction (transactional outbox):
     * a rollback drops the job, a commit makes it durable.
     */
    readonly transaction?: QueueTransaction;
}

Diekspor dari packages/queue/src/contracts.ts

FailedJob Interface

A job that exhausted its attempts.

interface FailedJob {
    readonly id: string | number;
    readonly queue: string;
    readonly name: string;
    readonly payload: unknown;
    readonly exception: string;
    readonly failedAt: string;
}

Diekspor dari packages/queue/src/contracts.ts

FakeQueue Interface

Test double that records dispatches instead of storing them.

interface FakeQueue extends Queue {
    readonly dispatched: readonly {
        readonly job: Job<never>;
        readonly payload: unknown;
        readonly options: DispatchOptions;
    }[];
    assertDispatched<P = unknown>(job: Job<P> | string, predicate?: (payload: P) => boolean): void;

Diekspor dari packages/queue/src/contracts.ts

Job Interface

A defined job.

interface Job<P = unknown> {
    readonly kind: 'job';
    readonly name: string;
    readonly handler: JobHandler<P>;
    readonly retries: number;
    readonly backoff: readonly number[];
    readonly timeoutMs: number | undefined;
    readonly queue: string;
}

Diekspor dari packages/queue/src/contracts.ts

JobContext Interface

Context handed to a job handler on every attempt.

interface JobContext {
    /** 1-based attempt number. */
    readonly attempt: number;
    /** Row id of the job in the driver (null for the sync driver). */
    readonly jobId: string | number | null;
    /** Queue the job was reserved from. */
    readonly queue: string;
    /** Aborted when `timeoutMs` elapses. */
    readonly signal: AbortSignal;
}

Diekspor dari packages/queue/src/contracts.ts

JobInput Interface

Input accepted by `defineJob`.

interface JobInput<P> {
    readonly name: string;
    readonly handler: JobHandler<P>;
    /** Additional attempts after the first one. Default 3. */
    readonly retries?: number;
    /** Delay in ms before retry n (the last entry repeats). Default `[1000, 5000, 30000]`. */
    readonly backoff?: readonly number[];
    /** Abort and fail an attempt after this many ms. */
    readonly timeoutMs?: number;
    /** Default queue for this job. */
    readonly queue?: string;
}

Diekspor dari packages/queue/src/contracts.ts

PushInput Interface

Tidak ada komentar dokumentasi.

interface PushInput {
    readonly name: string;
    readonly queue: string;
    readonly payload: unknown;
    readonly availableAt: number;
    readonly transaction?: QueueTransaction | undefined;
}

Diekspor dari packages/queue/src/contracts.ts

Queue Interface

Tidak ada komentar dokumentasi.

interface Queue {
    /** Register jobs so workers can resolve them by name. */
    register(...jobs: readonly Job<never>[]): void;
    dispatch<P>(job: Job<P>, payload: P, options?: DispatchOptions): Promise<void>;
    /** Run the worker loop. */
    work(options?: WorkOptions): Promise<WorkResult>;
    failed(): Promise<readonly FailedJob[]>;
    retry(id: string | number | 'all'): Promise<number>;
    size(queue?: string): Promise<number>;
}

Diekspor dari packages/queue/src/contracts.ts

QueueCommand Interface

Tidak ada komentar dokumentasi.

interface QueueCommand {
    readonly kind: 'command';
    readonly name: string;
    readonly description: string;
    readonly definition: {
        readonly description: string;
        readonly args?: Readonly<Record<string, ArgLike>>;
        readonly flags?: Readonly<Record<string, FlagLike>>;
        run(context: QueueCommandContext): Promise<number>;
    };
}

Diekspor dari packages/queue/src/commands.ts

QueueConfig Interface

Configuration of `queue()`.

interface QueueConfig {
    /**
     * `'database'` (default): jobs live in the `db` binding's `samveys_jobs` table.
     * `'sync'`: jobs run inline at dispatch (tests). Or pass any {@link QueueDriver}.
     */
    readonly driver?: 'database' | 'sync' | QueueDriver;
    /** Jobs workers may run, by name. */
    readonly jobs?: readonly Job<never>[];
    /** Database connection name for the `database` driver (default connection when omitted). */
    readonly connection?: string;
  …
Tampilkan seluruh deklarasi (14 baris)
interface QueueConfig {
    /**
     * `'database'` (default): jobs live in the `db` binding's `samveys_jobs` table.
     * `'sync'`: jobs run inline at dispatch (tests). Or pass any {@link QueueDriver}.
     */
    readonly driver?: 'database' | 'sync' | QueueDriver;
    /** Jobs workers may run, by name. */
    readonly jobs?: readonly Job<never>[];
    /** Database connection name for the `database` driver (default connection when omitted). */
    readonly connection?: string;
    readonly table?: string;
    readonly failedTable?: string;
    readonly visibilityMs?: number;
}

Diekspor dari packages/queue/src/plugin.ts

QueueDriver Interface

Storage backend for a queue.

interface QueueDriver {
    readonly name: string;
    push(input: PushInput): Promise<void>;
    /** Atomically reserve the next available job; two workers never get the same row. */
    reserve(queue: string, workerId: string, now: number): Promise<ReservedJob | null>;
    /** Delete a finished job. */
    complete(job: ReservedJob): Promise<void>;
    /** Put a job back with an incremented attempt count, available at `availableAt`. */
    release(job: ReservedJob, availableAt: number): Promise<void>;
    /** Move a job to the failed store. */
  …
Tampilkan seluruh deklarasi (16 baris)
interface QueueDriver {
    readonly name: string;
    push(input: PushInput): Promise<void>;
    /** Atomically reserve the next available job; two workers never get the same row. */
    reserve(queue: string, workerId: string, now: number): Promise<ReservedJob | null>;
    /** Delete a finished job. */
    complete(job: ReservedJob): Promise<void>;
    /** Put a job back with an incremented attempt count, available at `availableAt`. */
    release(job: ReservedJob, availableAt: number): Promise<void>;
    /** Move a job to the failed store. */
    fail(job: ReservedJob, error: Error): Promise<void>;
    failed(): Promise<readonly FailedJob[]>;
    /** Re-dispatch a failed job; returns false when the id is unknown. */
    retryFailed(id: string | number): Promise<boolean>;
    size(queue: string): Promise<number>;
}

Diekspor dari packages/queue/src/contracts.ts

QueueOptions Interface

Tidak ada komentar dokumentasi.

interface QueueOptions {
    /** A storage driver, or `'sync'` to run every job inline at dispatch time (tests, local dev). */
    readonly driver: QueueDriver | 'sync';
    /** Jobs known to workers by name. Dispatching a job registers it as well. */
    readonly jobs?: readonly Job<never>[];
    /** Identifies this worker in `reserved_by`. */
    readonly workerId?: string;
    readonly now?: () => number;

Diekspor dari packages/queue/src/queue.ts

QueueTransaction Interface

Minimal structural view of a database transaction. Any `@samveys/database` transaction satisfies it; it is used for the transactional outbox.

interface QueueTransaction {
    rawQuery(sql: string, bindings?: readonly unknown[]): Promise<unknown>;
}

Diekspor dari packages/queue/src/contracts.ts

ReservedJob Interface

A job row as reserved by a driver.

interface ReservedJob {
    readonly id: string | number;
    readonly queue: string;
    readonly name: string;
    readonly payload: unknown;
    /** Attempts made before this reservation. */
    readonly attempts: number;
}

Diekspor dari packages/queue/src/contracts.ts

WorkOptions Interface

Tidak ada komentar dokumentasi.

interface WorkOptions {
    readonly queue?: string;
    /** Process at most one job and return. */
    readonly once?: boolean;
    /** Stop after this many jobs. */
    readonly maxJobs?: number;
    /** Poll interval in ms when idle. Default 500. */
    readonly pollMs?: number;
    /** Aborting stops the loop after the current job. */
    readonly signal?: AbortSignal;
}

Diekspor dari packages/queue/src/contracts.ts

WorkResult Interface

Tidak ada komentar dokumentasi.

interface WorkResult {
    readonly processed: number;
    readonly failed: number;
}

Diekspor dari packages/queue/src/contracts.ts

Tipe (1)

JobHandler Tipe

Tidak ada komentar dokumentasi.

type JobHandler<P> = (payload: P, ctx: JobContext) => void | Promise<void>;

Diekspor dari packages/queue/src/contracts.ts