docs: update portal for WRNexusJS 0.8.0

This commit is contained in:
2026-08-02 23:57:41 +05:30
parent 9366895f78
commit 8d5d4b8f12
183 changed files with 14433 additions and 2492 deletions
+181 -12
View File
@@ -10,11 +10,11 @@ page wrnexusqueue {
<header class="topbar">
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.7.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.8.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
</header>
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
<main class="portal-main docs-layout">
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/queue</span></nav><section class="doc-intro"><span class="eyebrow">Data · Package reference</span><h1>@wrnexus/queue</h1><p>Background jobs with delay, concurrency, retry, and repetition.</p><div class="doc-meta"><span>v0.7.0</span><span>Private registry</span><span>Data</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/queue@0.7.0</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><blockquote>A background job queue with delays, retries + exponential backoff, recurring jobs, and concurrent workers.</blockquote>
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/queue</span></nav><section class="doc-intro"><span class="eyebrow">Data · Package reference</span><h1>@wrnexus/queue</h1><p>Background jobs with delay, concurrency, retry, and repetition.</p><div class="doc-meta"><span>v0.8.0</span><span>Private registry</span><span>Data</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/queue@0.8.0</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><blockquote>A background job queue with delays, retries + exponential backoff, recurring jobs, and concurrent workers.</blockquote>
<p>Part of the <strong>WRNexusJS</strong> framework — an SSR-first, Bun-native full-stack web framework.</p>
<h3 id="overview">Overview</h3>
<p><code>@wrnexus/queue</code> is a server-side in-process job queue. You register named workers, enqueue jobs (optionally delayed or recurring), and let the queue poll and run them on a timer — with per-job retry limits and doubling backoff between attempts. The default store lives in memory; the design allows a pluggable driver to back it with Redis/SQL for durability across restarts. Reach for it when you need to defer work (emails, webhooks, cleanup) off the request path without a heavyweight external broker. Tests can drive it deterministically via <code>drain()</code>.</p>
@@ -29,18 +29,21 @@ page wrnexusqueue {
<h4 id="queueoptions"><code>QueueOptions</code></h4>
<div class="table-wrap"><table>
<thead><tr><th>Option</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody><tr><td><code>maxAttempts</code></td><td><code>number</code></td><td><code>3</code></td><td>Default max attempts per job before it is dead-lettered.</td></tr><tr><td><code>backoffMs</code></td><td><code>number</code></td><td><code>1000</code></td><td>Base retry backoff in ms; doubles per attempt.</td></tr><tr><td><code>pollMs</code></td><td><code>number</code></td><td><code>250</code></td><td>Poll interval used once <code>start()</code> is called (ms).</td></tr><tr><td><code>onFailed</code></td><td><code>(job: Job, error: unknown) =&gt; void</code></td><td>—</td><td>Called when a job exhausts its attempts.</td></tr><tr><td><code>now</code></td><td><code>() =&gt; number</code></td><td><code>Date.now</code></td><td>Clock injection for deterministic tests.</td></tr></tbody></table></div>
<tbody><tr><td><code>maxAttempts</code></td><td><code>number</code></td><td><code>3</code></td><td>Default max attempts per job before it is dead-lettered.</td></tr><tr><td><code>backoffMs</code></td><td><code>number</code></td><td><code>1000</code></td><td>Base retry backoff in ms; doubles per attempt.</td></tr><tr><td><code>pollMs</code></td><td><code>number</code></td><td><code>250</code></td><td>Poll interval used once <code>start()</code> is called (ms).</td></tr><tr><td><code>onFailed</code></td><td><code>(job: Job, error: unknown) =&gt; void</code></td><td>—</td><td>Called when a job exhausts its attempts.</td></tr><tr><td><code>concurrency</code></td><td><code>number</code></td><td>unlimited</td><td>Maximum jobs claimed by one <code>drain()</code> call.</td></tr><tr><td><code>capacity</code></td><td><code>number</code></td><td>unlimited</td><td>Maximum queued plus active jobs before adds reject.</td></tr><tr><td><code>now</code></td><td><code>() =&gt; number</code></td><td><code>Date.now</code></td><td>Clock injection for deterministic tests.</td></tr></tbody></table></div>
<h4 id="queue"><code>Queue</code></h4>
<p>The object returned by <code>createQueue</code>.</p>
<div class="table-wrap"><table>
<thead><tr><th>Method</th><th>Signature</th><th>Description</th></tr></thead>
<tbody><tr><td><code>add</code></td><td><code>add&lt;T&gt;(name, data: T, options?: AddOptions): Promise&lt;Job&lt;T&gt;&gt;</code></td><td>Enqueue a job under a worker name. Returns the created job.</td></tr><tr><td><code>process</code></td><td><code>process&lt;T&gt;(name, handler: JobHandler&lt;T&gt;): void</code></td><td>Register the worker that runs jobs of the given name.</td></tr><tr><td><code>drain</code></td><td><code>drain(now?: number): Promise&lt;number&gt;</code></td><td>Run every job whose <code>runAt ≤ now</code>, once. Returns how many ran.</td></tr><tr><td><code>start</code></td><td><code>start(): void</code></td><td>Begin polling every <code>pollMs</code>. No-op if already started.</td></tr><tr><td><code>stop</code></td><td><code>stop(): void</code></td><td>Stop the poll timer.</td></tr><tr><td><code>size</code></td><td><code>size(): number</code></td><td>Number of jobs currently queued.</td></tr></tbody></table></div>
<tbody><tr><td><code>add</code></td><td><code>add&lt;T&gt;(name, data: T, options?: AddOptions): Promise&lt;Job&lt;T&gt;&gt;</code></td><td>Enqueue a job under a worker name. Returns the created job.</td></tr><tr><td><code>process</code></td><td><code>process&lt;T&gt;(name, handler: JobHandler&lt;T&gt;): void</code></td><td>Register the worker that runs jobs of the given name.</td></tr><tr><td><code>drain</code></td><td><code>drain(now?: number): Promise&lt;number&gt;</code></td><td>Run every job whose <code>runAt ≤ now</code>, once. Returns how many ran.</td></tr><tr><td><code>start</code></td><td><code>start(): void</code></td><td>Begin polling every <code>pollMs</code>. No-op if already started.</td></tr><tr><td><code>stop</code></td><td><code>stop(): void</code></td><td>Stop the poll timer.</td></tr><tr><td><code>shutdown</code></td><td><code>shutdown(&#123; force? &#125;): Promise&lt;void&gt;</code></td><td>Stop accepting jobs and await active work; force aborts it.</td></tr><tr><td><code>size</code></td><td><code>size(): number</code></td><td>Number of jobs currently queued.</td></tr><tr><td><code>get/list</code></td><td><code>get(id)</code> / <code>list(name?)</code></td><td>Inspect defensive copies of pending jobs.</td></tr><tr><td><code>cancel</code></td><td><code>cancel(id): boolean</code></td><td>Remove queued work or abort an active handler.</td></tr><tr><td><code>failed</code></td><td><code>failed(): Job[]</code></td><td>Inspect exhausted jobs in the dead-letter collection.</td></tr><tr><td><code>retry</code></td><td><code>retry(id): Promise&lt;boolean&gt;</code></td><td>Reset and requeue a dead-lettered job.</td></tr></tbody></table></div>
<h4 id="addoptions"><code>AddOptions</code></h4>
<div class="table-wrap"><table>
<thead><tr><th>Option</th><th>Type</th><th>Description</th></tr></thead>
<tbody><tr><td><code>delayMs</code></td><td><code>number</code></td><td>Delay before the job becomes runnable (ms).</td></tr><tr><td><code>maxAttempts</code></td><td><code>number</code></td><td>Max attempts before dead-lettering. Defaults to the queue's <code>maxAttempts</code>.</td></tr><tr><td><code>repeat</code></td><td><code>number</code></td><td>Re-enqueue this job this many ms after each successful run (recurring).</td></tr></tbody></table></div>
<tbody><tr><td><code>delayMs</code></td><td><code>number</code></td><td>Delay before the job becomes runnable (ms).</td></tr><tr><td><code>maxAttempts</code></td><td><code>number</code></td><td>Max attempts before dead-lettering. Defaults to the queue's <code>maxAttempts</code>.</td></tr><tr><td><code>repeat</code></td><td><code>number</code></td><td>Re-enqueue this job this many ms after each successful run (recurring).</td></tr><tr><td><code>priority</code></td><td><code>number</code></td><td>Higher values are selected first among due jobs.</td></tr><tr><td><code>idempotencyKey</code></td><td><code>string</code></td><td>Return the matching pending job instead of enqueueing a duplicate.</td></tr></tbody></table></div>
<h4 id="jobhandler-t"><code>JobHandler&lt;T&gt;</code></h4>
<pre data-language="ts"><code>type JobHandler&lt;T = unknown&gt; = (job: Job&lt;T&gt;) =&gt; void | Promise&lt;void&gt;;</code></pre>
<pre data-language="ts"><code>type JobHandler&lt;T = unknown&gt; = (
job: Job&lt;T&gt;,
context: &#123; signal: AbortSignal &#125;,
) =&gt; void | Promise&lt;void&gt;;</code></pre>
<h4 id="job-t"><code>Job&lt;T&gt;</code></h4>
<pre data-language="ts"><code>interface Job&lt;T = unknown&gt; &#123;
id: string; // e.g. &quot;job_1&quot;
@@ -66,6 +69,9 @@ queue.process&lt;&#123; to: string &#125;&gt;(&quot;email&quot;, async (job) =&g
await queue.add(&quot;email&quot;, &#123; to: &quot;a@b.com&quot; &#125;, &#123; delayMs: 5000, maxAttempts: 3 &#125;);
queue.start(); // begin polling; queue.stop() to halt</code></pre>
<p>Use <code>context.signal</code> in network/database calls so forced shutdown and active cancellation finish promptly. For process termination, prefer <code>await queue.shutdown()</code>; use <code>&#123; force: true &#125;</code> only after your grace period.</p>
<h4 id="durable-queue">Durable queue</h4>
<p><code>createDurableQueue(&#123; store &#125;)</code> retains jobs until their handler succeeds and supports atomic leases when a driver implements <code>QueueStore.claim</code>. It exposes the same cancellation/shutdown behavior plus <code>list</code>, <code>failed</code>, and <code>retry</code>. The included <code>memoryQueueStore()</code> is useful for tests; production Redis/SQL drivers should make <code>claim()</code> atomic to prevent two workers executing one job.</p>
<h4 id="recurring-jobs">Recurring jobs</h4>
<p>Pass <code>repeat</code> to re-enqueue a job a fixed interval after each successful run:</p>
<pre data-language="ts"><code>queue.process(&quot;heartbeat&quot;, async () =&gt; ping());
@@ -89,6 +95,20 @@ await queue.add(&quot;task&quot;, &#123;&#125;, &#123; delayMs: 5000 &#125;);
clock = 5000;
const ran = await queue.drain(); // =&gt; 1</code></pre>
<h4 id="durable-workflows-and-approvals">Durable workflows and approvals</h4>
<p><code>createWorkflowEngine(store)</code> executes dependency-ordered steps and persists every transition, result, progress update, failure, cancellation, and approval record. Approval steps pause safely and can resume after a process restart because the snapshot lives in the supplied <code>WorkflowStore</code>.</p>
<pre data-language="ts"><code>const workflow = defineDurableWorkflow(&#123;
name: &quot;publish-report&quot;,
steps: [
&#123; name: &quot;build&quot;, run: buildReport &#125;,
&#123; name: &quot;approve&quot;, dependsOn: [&quot;build&quot;], approval: true, run: (report) =&gt; report &#125;,
&#123; name: &quot;publish&quot;, dependsOn: [&quot;approve&quot;], run: publishReport &#125;,
],
&#125;);
const run = await engine.start(workflow, input);
await engine.approve(workflow, run.id, &quot;approve&quot;, currentUser.id);</code></pre>
<p>Use <code>memoryWorkflowStore()</code> for tests. Production stores implement the small <code>get</code>, <code>put</code>, and <code>list</code> contract using the same transactional database or durable service as the application.</p>
<h3 id="retry-backoff-behavior">Retry &amp; backoff behavior</h3>
<ul>
<li>On a thrown handler error, the job is retried while <code>attempts &lt; maxAttempts</code>.</li>
@@ -105,7 +125,9 @@ const ran = await queue.drain(); // =&gt; 1</code></pre>
<li>The default store is in-process, so queued jobs do not survive a restart; a</li>
<p>pluggable driver is intended for backing it with Redis/SQL for durability.</p>
<li>Works alongside <code>@wrnexus/core</code> for offloading work from the request path.</li>
</ul></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>/**
</ul></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>import &#123; ExecutionContext &#125; from '@wrnexus/core';
/**
* Persistence contract for the durable queue.
*
* Distributed drivers should implement `claim()` atomically and exclude leased
@@ -126,20 +148,142 @@ interface DurableQueueOptions &#123;
workerId?: string;
maxAttempts?: number;
concurrency?: number;
capacity?: number;
leaseMs?: number;
backoff?: (attempt: number) =&gt; number;
now?: () =&gt; number;
onDeadLetter?: (job: Job, error: unknown) =&gt; void | Promise&lt;void&gt;;
context?: (job: Job, signal: AbortSignal) =&gt; ExecutionContext;
&#125;
interface DurableQueue &#123;
add&lt;T&gt;(name: string, data: T, options?: AddOptions): Promise&lt;Job&lt;T&gt;&gt;;
process&lt;T&gt;(name: string, handler: JobHandler&lt;T&gt;): void;
drain(): Promise&lt;number&gt;;
cancel(id: string): Promise&lt;boolean&gt;;
shutdown(options?: &#123;
force?: boolean;
&#125;): Promise&lt;void&gt;;
list(name?: string): Promise&lt;Job[]&gt;;
failed(): Job[];
retry(id: string): Promise&lt;boolean&gt;;
&#125;
declare function createDurableQueue(options?: DurableQueueOptions): DurableQueue;
interface RedisQueueClient &#123;
get(key: string): Promise&lt;string | null&gt;;
set(key: string, value: string, options?: &#123;
NX?: boolean;
PX?: number;
&#125;): Promise&lt;unknown&gt;;
del(...keys: string[]): Promise&lt;unknown&gt;;
zadd(key: string, score: number, member: string): Promise&lt;unknown&gt;;
zrem(key: string, member: string): Promise&lt;unknown&gt;;
zrangebyscore(key: string, min: number, max: number, options?: &#123;
limit: [number, number];
&#125;): Promise&lt;string[]&gt;;
smembers(key: string): Promise&lt;string[]&gt;;
sadd(key: string, member: string): Promise&lt;unknown&gt;;
srem(key: string, member: string): Promise&lt;unknown&gt;;
&#125;
/** Redis-backed queue store using only the common client command surface. */
declare function redisQueueStore(client: RedisQueueClient, prefix?: string): QueueStore;
interface SqlQueueClient &#123;
query&lt;T = Record&lt;string, unknown&gt;&gt;(sql: string, parameters?: unknown[]): Promise&lt;&#123;
rows: T[];
&#125;&gt;;
&#125;
/** PostgreSQL store with atomic SKIP LOCKED leasing and JSON payloads. */
declare function postgresQueueStore(db: SqlQueueClient, table?: string): QueueStore;
declare const POSTGRES_QUEUE_SCHEMA = &quot;CREATE TABLE IF NOT EXISTS wrnexus_jobs (\n id text PRIMARY KEY, name text NOT NULL, payload jsonb NOT NULL, run_at bigint NOT NULL,\n priority integer NOT NULL DEFAULT 0, lease_owner text, lease_until bigint\n); CREATE INDEX IF NOT EXISTS wrnexus_jobs_due ON wrnexus_jobs (run_at, priority DESC);&quot;;
interface ScheduledJob&lt;T = unknown&gt; &#123;
name: string;
data: T;
everyMs: number;
options?: AddOptions;
&#125;
interface QueueScheduler &#123;
start(): void;
stop(): void;
tick(now?: number): Promise&lt;number&gt;;
snapshot(): &#123;
running: boolean;
schedules: number;
nextRuns: Record&lt;string, number&gt;;
&#125;;
&#125;
/** Restart-safe scheduler when used with a durable queue and stable idempotency buckets. */
declare function createQueueScheduler(queue: DurableQueue, schedules: ScheduledJob[], options?: &#123;
pollMs?: number;
now?: () =&gt; number;
&#125;): QueueScheduler;
declare function addBatch&lt;T&gt;(queue: DurableQueue, name: string, values: T[], options?: AddOptions): Promise&lt;Job&lt;T&gt;[]&gt;;
interface QueueDashboardSnapshot &#123;
generatedAt: number;
pending: number;
failed: number;
byName: Record&lt;string, number&gt;;
oldestRunAt?: number;
&#125;
declare function queueDashboardSnapshot(queue: DurableQueue): Promise&lt;QueueDashboardSnapshot&gt;;
declare function renderQueueDashboard(snapshot: QueueDashboardSnapshot): string;
/** Long-running scheduler/worker loop suitable for a dedicated process or container. */
declare function runQueueDaemon(queue: DurableQueue, scheduler: QueueScheduler, options?: &#123;
signal?: AbortSignal;
pollMs?: number;
onError?: (error: unknown) =&gt; void;
&#125;): Promise&lt;void&gt;;
type WorkflowStatus = &quot;pending&quot; | &quot;running&quot; | &quot;waiting-approval&quot; | &quot;completed&quot; | &quot;failed&quot; | &quot;cancelled&quot;;
interface WorkflowStep$1&lt;I = unknown, O = unknown&gt; &#123;
name: string;
dependsOn?: string[];
approval?: boolean;
run(input: I, context: WorkflowRunContext): O | Promise&lt;O&gt;;
&#125;
interface WorkflowRunContext &#123;
workflowId: string;
step: string;
results: Readonly&lt;Record&lt;string, unknown&gt;&gt;;
signal: AbortSignal;
progress(value: number, message?: string): void;
&#125;
interface WorkflowSnapshot &#123;
id: string;
name: string;
status: WorkflowStatus;
input: unknown;
results: Record&lt;string, unknown&gt;;
completed: string[];
waitingFor?: string;
progress: number;
message?: string;
error?: string;
updatedAt: number;
&#125;
interface WorkflowStore &#123;
get(id: string): Promise&lt;WorkflowSnapshot | null&gt;;
put(snapshot: WorkflowSnapshot): Promise&lt;void&gt;;
list(): Promise&lt;WorkflowSnapshot[]&gt;;
&#125;
declare function memoryWorkflowStore(): WorkflowStore;
interface WorkflowDefinition&lt;I = unknown&gt; &#123;
name: string;
steps: WorkflowStep$1&lt;any, any&gt;[];
/** Compile-time input marker; definitions do not store runtime input values. */
readonly __input?: I;
&#125;
interface WorkflowEngine &#123;
start&lt;I&gt;(definition: WorkflowDefinition&lt;I&gt;, input: I, id?: string): Promise&lt;WorkflowSnapshot&gt;;
resume&lt;I&gt;(definition: WorkflowDefinition&lt;I&gt;, id: string): Promise&lt;WorkflowSnapshot&gt;;
approve&lt;I&gt;(definition: WorkflowDefinition&lt;I&gt;, id: string, step: string, actor: string): Promise&lt;WorkflowSnapshot&gt;;
cancel(id: string): Promise&lt;boolean&gt;;
get(id: string): Promise&lt;WorkflowSnapshot | null&gt;;
list(): Promise&lt;WorkflowSnapshot[]&gt;;
&#125;
declare function createWorkflowEngine(store?: WorkflowStore): WorkflowEngine;
declare function defineDurableWorkflow&lt;I&gt;(definition: WorkflowDefinition&lt;I&gt;): WorkflowDefinition&lt;I&gt;;
/**
* @wrnexus/queue — a background job queue with delays, retries + backoff, and
* concurrent workers. The default store is in-process; a pluggable driver lets
@@ -165,7 +309,13 @@ interface Job&lt;T = unknown&gt; &#123;
idempotencyKey?: string;
createdAt: number;
&#125;
type JobHandler&lt;T = unknown&gt; = (job: Job&lt;T&gt;) =&gt; void | Promise&lt;void&gt;;
interface JobContext &#123;
/** Aborted when an active job is cancelled or the queue is force-stopped. */
signal: AbortSignal;
/** The same trusted context shape used by HTTP, actions, realtime and webhooks. */
execution: ExecutionContext;
&#125;
type JobHandler&lt;T = unknown&gt; = (job: Job&lt;T&gt;, context: JobContext) =&gt; void | Promise&lt;void&gt;;
interface AddOptions &#123;
/** Delay before the job becomes runnable (ms). */
delayMs?: number;
@@ -189,8 +339,11 @@ interface QueueOptions &#123;
onFailed?: (job: Job, error: unknown) =&gt; void;
/** Maximum jobs executed in one drain. Default: unlimited. */
concurrency?: number;
/** Maximum queued + active jobs. Adds reject once this limit is reached. */
capacity?: number;
/** Clock injection (tests). Default Date.now. */
now?: () =&gt; number;
context?: (job: Job, signal: AbortSignal) =&gt; ExecutionContext;
&#125;
interface Queue &#123;
add&lt;T&gt;(name: string, data: T, options?: AddOptions): Promise&lt;Job&lt;T&gt;&gt;;
@@ -199,10 +352,16 @@ interface Queue &#123;
drain(now?: number): Promise&lt;number&gt;;
start(): void;
stop(): void;
/** Stop accepting work and wait for active handlers (or abort them). */
shutdown(options?: &#123;
force?: boolean;
&#125;): Promise&lt;void&gt;;
size(): number;
get(id: string): Job | undefined;
list(name?: string): Job[];
cancel(id: string): boolean;
failed(): Job[];
retry(id: string): Promise&lt;boolean&gt;;
&#125;
interface JobDefinition&lt;I&gt; &#123;
name: string;
@@ -222,7 +381,7 @@ declare function defineWorkflow&lt;T&gt;(name: string, steps: Array&lt;WorkflowS
declare function cronToInterval(cron: string): number;
declare function createQueue(options?: QueueOptions): Queue;
export &#123; type AddOptions, type DurableQueue, type DurableQueueOptions, type Job, type JobDefinition, type JobHandler, type Queue, type QueueOptions, type QueueStore, type WorkflowStep, createDurableQueue, createQueue, cronToInterval, defineJob, defineWorkflow, memoryQueueStore &#125;;
export &#123; type AddOptions, type DurableQueue, type DurableQueueOptions, type Job, type JobContext, type JobDefinition, type JobHandler, POSTGRES_QUEUE_SCHEMA, type Queue, type QueueDashboardSnapshot, type QueueOptions, type QueueScheduler, type QueueStore, type RedisQueueClient, type ScheduledJob, type SqlQueueClient, type WorkflowDefinition, type WorkflowEngine, type WorkflowRunContext, type WorkflowSnapshot, type WorkflowStatus, type WorkflowStep, type WorkflowStore, addBatch, createDurableQueue, createQueue, createQueueScheduler, createWorkflowEngine, cronToInterval, defineDurableWorkflow, defineJob, defineWorkflow, memoryQueueStore, memoryWorkflowStore, postgresQueueStore, queueDashboardSnapshot, redisQueueStore, renderQueueDashboard, runQueueDaemon &#125;;
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>Register workers, enqueue jobs, then start the poller</h3><pre data-language="ts"><code>import &#123; createQueue &#125; from &quot;@wrnexus/queue&quot;;
const queue = createQueue(&#123; maxAttempts: 3, backoffMs: 1000 &#125;);
@@ -249,10 +408,20 @@ queue.process(&quot;task&quot;, async () =&gt; &#123;
await queue.add(&quot;task&quot;, &#123;&#125;, &#123; delayMs: 5000 &#125;);
clock = 5000;
const ran = await queue.drain(); // =&gt; 1</code></pre></article></div></section></article>
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-4" href="#createqueue-options-queue">createQueue(options?): Queue</a><a class="toc-level-4" href="#queueoptions">QueueOptions</a><a class="toc-level-4" href="#queue">Queue</a><a class="toc-level-4" href="#addoptions">AddOptions</a><a class="toc-level-4" href="#jobhandler-t">JobHandler&lt;T&gt;</a><a class="toc-level-4" href="#job-t">Job&lt;T&gt;</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-4" href="#recurring-jobs">Recurring jobs</a><a class="toc-level-4" href="#handling-permanent-failures">Handling permanent failures</a><a class="toc-level-4" href="#deterministic-testing">Deterministic testing</a><a class="toc-level-3" href="#retry-backoff-behavior">Retry &amp; backoff behavior</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
const ran = await queue.drain(); // =&gt; 1</code></pre></article><article class="example-card"><h3>Durable workflows and approvals</h3><pre data-language="ts"><code>const workflow = defineDurableWorkflow(&#123;
name: &quot;publish-report&quot;,
steps: [
&#123; name: &quot;build&quot;, run: buildReport &#125;,
&#123; name: &quot;approve&quot;, dependsOn: [&quot;build&quot;], approval: true, run: (report) =&gt; report &#125;,
&#123; name: &quot;publish&quot;, dependsOn: [&quot;approve&quot;], run: publishReport &#125;,
],
&#125;);
const run = await engine.start(workflow, input);
await engine.approve(workflow, run.id, &quot;approve&quot;, currentUser.id);</code></pre></article></div></section></article>
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-4" href="#createqueue-options-queue">createQueue(options?): Queue</a><a class="toc-level-4" href="#queueoptions">QueueOptions</a><a class="toc-level-4" href="#queue">Queue</a><a class="toc-level-4" href="#addoptions">AddOptions</a><a class="toc-level-4" href="#jobhandler-t">JobHandler&lt;T&gt;</a><a class="toc-level-4" href="#job-t">Job&lt;T&gt;</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-4" href="#durable-queue">Durable queue</a><a class="toc-level-4" href="#recurring-jobs">Recurring jobs</a><a class="toc-level-4" href="#handling-permanent-failures">Handling permanent failures</a><a class="toc-level-4" href="#deterministic-testing">Deterministic testing</a><a class="toc-level-4" href="#durable-workflows-and-approvals">Durable workflows and approvals</a><a class="toc-level-3" href="#retry-backoff-behavior">Retry &amp; backoff behavior</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
</main>
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.7.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.8.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
<BackToTop />
</div>
}