@orkestrel/worker 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,13 +10,13 @@ observable (a typed `emitter` re-exposes the underlying queue's job lifecycle
10
10
  — `enqueue` / `start` / `retry` / `success` / `failure` / `abort` / `drain`).
11
11
  For CPU-parallel work, the server surface's `createNodeWorker` specializes the
12
12
  core `createWorker` over a pool of `node:worker_threads`, crossing the
13
- structured-clone boundary with zero `as` via `input` / `result` guards. Each
13
+ structured-clone boundary with zero `as` through `input` / `result` guards. Each
14
14
  thread handler receives `{ id, signal }`: `id` is the Queue's stable idempotency
15
15
  key across retries and crash restore, while `signal` is per attempt. The wire
16
16
  protocol separately mints a fresh correlation id for each dispatch so a stale
17
17
  reply cannot settle a later retry. The stable id identifies work, not a caller,
18
18
  and is not authentication or authorization evidence; per-job consumer context
19
- remains explicit structured-cloneable input rather than ambient thread state.
19
+ is explicit, structured-cloneable input rather than ambient thread state.
20
20
  Part of the `@orkestrel` line.
21
21
 
22
22
  ## Install
@@ -27,6 +27,8 @@ npm install @orkestrel/worker
27
27
 
28
28
  ## Requirements
29
29
 
30
+ The package runs under these conditions:
31
+
30
32
  - Node.js >= 22.12.0
31
33
  - ESM and CommonJS builds ship for both the core and server entry points
32
34
 
@@ -68,11 +70,11 @@ await worker.destroy()
68
70
 
69
71
  For the full surface — the `Worker` facade, `createNodeWorker` / `serveWorker`,
70
72
  the durable `createJSONQueueStore`, the observable `emitter`, and usage
71
- patterns — see [`guides/src/worker.md`](guides/src/worker.md).
73
+ patterns — see [`guides/worker.md`](guides/worker.md).
72
74
 
73
75
  ## Package
74
76
 
75
- Published with two entry points per the `exports` field in `package.json`:
77
+ Published with the entry points the `exports` field in `package.json` names:
76
78
  the environment-agnostic core (`.`) and the Node-only server surface
77
79
  (`./server`).
78
80
 
@@ -4,8 +4,8 @@ let _orkestrel_pool = require("@orkestrel/pool");
4
4
  let _orkestrel_queue = require("@orkestrel/queue");
5
5
  //#region src/core/Worker.ts
6
6
  /**
7
- * A resource-backed job worker — a thin facade composing a `Queue` (`@orkestrel/queue`)
8
- * with a `Pool` (`@orkestrel/pool`).
7
+ * Represents a resource-backed job worker — a thin facade composing a `Queue`
8
+ * (`@orkestrel/queue`) with a `Pool` (`@orkestrel/pool`).
9
9
  *
10
10
  * @remarks
11
11
  * - **Composition, not reimplementation.** The Worker owns a `Pool` (built from
@@ -20,7 +20,7 @@ let _orkestrel_queue = require("@orkestrel/queue");
20
20
  * options. At most one resource exists per in-flight job by default, and idle resources are
21
21
  * reused across jobs.
22
22
  * - **Acquire over the attempt signal.** Each job acquires using the attempt's
23
- * `execution.signal`, so an `abort` / `timeout` while waiting for a resource rejects
23
+ * `context.signal`, so an `abort` / `timeout` while waiting for a resource rejects
24
24
  * the acquire — the Queue then handles retry / rejection, and there is no token to
25
25
  * release (the resource was never leased).
26
26
  * - **Lifecycle (§10).** `enqueue` / `restore` / `start` / `stop` / `pause` / `resume` /
@@ -120,10 +120,10 @@ var Worker = class {
120
120
  this.#teardown(ending);
121
121
  return ending.promise;
122
122
  }
123
- async #handle(input, execution) {
124
- const token = await this.#pool.acquire(execution.signal);
123
+ async #handle(input, context) {
124
+ const token = await this.#pool.acquire(context.signal);
125
125
  try {
126
- return await this.#handler(input, token.value, execution);
126
+ return await this.#handler(input, token.value, context);
127
127
  } finally {
128
128
  token.release();
129
129
  }
@@ -159,14 +159,14 @@ var Worker = class {
159
159
  //#endregion
160
160
  //#region src/core/factories.ts
161
161
  /**
162
- * Create a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
162
+ * Creates a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
163
163
  * (`@orkestrel/pool`). Each enqueued input runs through the handler against an
164
164
  * automatically acquired pooled resource (released when the job settles), with the
165
165
  * queue's bounded concurrency, retries, and per-attempt timeout / abort.
166
166
  *
167
167
  * @remarks
168
- * The pool's `max` defaults to `concurrency`, so resources match the jobs in flight and
169
- * are reused across jobs. A handler that throws still releases its resource (the
168
+ * Default for the pool's `max`: the `concurrency` value, so resources match the jobs in flight.
169
+ * Resources are reused across jobs. A handler that throws still releases its resource (the
170
170
  * acquire/release pair brackets the call in a `finally`), so a later job reuses it. The
171
171
  * lifecycle (`start` / `stop` / `pause` / `resume` / `abort` / `clear` / `destroy`)
172
172
  * delegates to the queue; `destroy` also tears the pool down. Observable (§13): a typed
@@ -175,8 +175,8 @@ var Worker = class {
175
175
  * @typeParam TInput - The work input each job carries
176
176
  * @typeParam TResource - The pooled resource each job runs against
177
177
  * @typeParam TResult - The value the handler resolves for a job
178
- * @param options - The `handler` and `pool` plus optional `concurrency` (default `1`),
179
- * `retries` (default `0`), and a default per-attempt `timeout` in milliseconds
178
+ * @param options - The `handler` and `pool` plus the optional `concurrency`, `retries`,
179
+ * `timeout`, `store`, `on`, and `error` keys (see {@link WorkerOptions})
180
180
  * @returns A working {@link WorkerInterface}
181
181
  *
182
182
  * @example
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["#queue","#pool","#emitter","#handler","#handle","#bridge","#ending","#teardown"],"sources":["../../../src/core/Worker.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { EmitterInterface } from '@orkestrel/emitter'\nimport type { QueueEntryOptions, QueueExecution } from '@orkestrel/queue'\nimport type { WorkerEventMap, WorkerHandler, WorkerInterface, WorkerOptions } from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { Pool } from '@orkestrel/pool'\nimport { Queue } from '@orkestrel/queue'\n\n/**\n * A resource-backed job worker — a thin facade composing a `Queue` (`@orkestrel/queue`)\n * with a `Pool` (`@orkestrel/pool`).\n *\n * @remarks\n * - **Composition, not reimplementation.** The Worker owns a `Pool` (built from\n * `options.pool`) and a `Queue` whose handler ACQUIRES a pooled resource, runs the\n * user handler against it, and RELEASES it in a `finally`. All concurrency, retries,\n * timeout, and lifecycle are the Queue's — the Worker adds only the resource pairing.\n * - **Resource ↔ concurrency.** The queue strictly validates `concurrency` as a positive\n * safe integer after caller options are captured once. Only `undefined` defaults\n * `concurrency` to `1` or pool `max` to that value; runtime `null` reaches the owning\n * validator. The queue validates before the pool option is read; every declared pool member\n * is then captured once by direct access, preserving inherited and non-enumerable structural\n * options. At most one resource exists per in-flight job by default, and idle resources are\n * reused across jobs.\n * - **Acquire over the attempt signal.** Each job acquires using the attempt's\n * `execution.signal`, so an `abort` / `timeout` while waiting for a resource rejects\n * the acquire — the Queue then handles retry / rejection, and there is no token to\n * release (the resource was never leased).\n * - **Lifecycle (§10).** `enqueue` / `restore` / `start` / `stop` / `pause` / `resume` /\n * `abort` / `clear` delegate to the queue; `count` / `active` / `paused` / `stopped`\n * read it. `stop` / `abort` / `clear` return the queue's own cleanup barriers.\n * `destroy` returns one stable barrier while it tears down the queue, then the pool,\n * and destroys the worker emitter last. A sole cleanup failure is preserved by\n * identity; failures from both layers become an ordered `AggregateError`.\n * - **Durability.** An optional `store` is passed straight through to the queue, so the\n * worker's outstanding jobs persist; `restore` re-runs them (delegated to the queue).\n * - **Observable (§13).** The owned {@link emitter} ({@link WorkerEventMap}) RE-EXPOSES the\n * underlying queue's job lifecycle (`enqueue` / `start` / `retry` / `success` / `failure` /\n * `abort` / `drain`) as the worker's OWN events — bridged from the inner queue's emitter at\n * construction — so a consumer observes the worker without reaching through to internals.\n * The bridge re-emits directly on the worker's own emitter; the worker emitter isolates a\n * listener throw and routes it to its `error` handler (the `error` option), so a buggy\n * worker observer can never corrupt the inner queue or pool — the bridge listener never\n * throws, so the inner queue's own emit stays balanced. The pool's create / acquire /\n * release events stay the pool's internal concern (a Worker manages its own resources);\n * observe a `Pool` directly for those.\n */\nexport class Worker<TInput, TResource, TResult> implements WorkerInterface<TInput, TResult> {\n\treadonly #queue: Queue<TInput, TResult>\n\treadonly #pool: Pool<TResource>\n\t// The PUSH observation surface (§13) — the worker's OWN emitter, fed by the queue→worker\n\t// bridge. The emitter isolates a worker observer's throw (routing it to the `error`\n\t// handler), so it never escapes into queue or pool.\n\treadonly #emitter: Emitter<WorkerEventMap<TResult>>\n\treadonly #handler: WorkerHandler<TInput, TResource, TResult>\n\t#ending: PromiseWithResolvers<void> | undefined\n\n\tconstructor(options: WorkerOptions<TInput, TResource, TResult>) {\n\t\tconst {\n\t\t\tconcurrency: capturedConcurrency,\n\t\t\thandler,\n\t\t\ton,\n\t\t\terror,\n\t\t\tretries,\n\t\t\ttimeout,\n\t\t\tstore,\n\t\t} = options\n\t\tconst concurrency = capturedConcurrency === undefined ? 1 : capturedConcurrency\n\t\tthis.#handler = handler\n\t\tthis.#emitter = new Emitter<WorkerEventMap<TResult>>({\n\t\t\t...(on !== undefined ? { on } : {}),\n\t\t\t...(error !== undefined ? { error } : {}),\n\t\t})\n\t\tthis.#queue = new Queue<TInput, TResult>({\n\t\t\thandler: this.#handle.bind(this),\n\t\t\tconcurrency,\n\t\t\t...(retries !== undefined ? { retries } : {}),\n\t\t\t...(timeout !== undefined ? { timeout } : {}),\n\t\t\t...(store !== undefined ? { store } : {}),\n\t\t})\n\t\tconst pool = options.pool\n\t\tconst { max, on: poolOn, error: poolError, create, destroy, validate } = pool\n\t\tthis.#pool = new Pool<TResource>({\n\t\t\tcreate,\n\t\t\tmax: max === undefined ? concurrency : max,\n\t\t\t...(poolOn !== undefined ? { on: poolOn } : {}),\n\t\t\t...(poolError !== undefined ? { error: poolError } : {}),\n\t\t\t...(destroy !== undefined ? { destroy } : {}),\n\t\t\t...(validate !== undefined ? { validate } : {}),\n\t\t})\n\t\tthis.#bridge()\n\t}\n\n\tget emitter(): EmitterInterface<WorkerEventMap<TResult>> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#queue.count\n\t}\n\n\tget active(): number {\n\t\treturn this.#queue.active\n\t}\n\n\tget paused(): boolean {\n\t\treturn this.#queue.paused\n\t}\n\n\tget stopped(): boolean {\n\t\treturn this.#queue.stopped\n\t}\n\n\tenqueue(input: TInput, options?: QueueEntryOptions): Promise<TResult> {\n\t\treturn this.#queue.enqueue(input, options)\n\t}\n\n\trestore(): Promise<void> {\n\t\treturn this.#queue.restore()\n\t}\n\n\tstart(): void {\n\t\tthis.#queue.start()\n\t}\n\n\tstop(): Promise<void> {\n\t\treturn this.#queue.stop()\n\t}\n\n\tpause(): void {\n\t\tthis.#queue.pause()\n\t}\n\n\tresume(): void {\n\t\tthis.#queue.resume()\n\t}\n\n\tabort(reason?: unknown): Promise<void> {\n\t\treturn this.#queue.abort(reason)\n\t}\n\n\tclear(): Promise<void> {\n\t\treturn this.#queue.clear()\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tif (this.#ending !== undefined) return this.#ending.promise\n\t\tconst ending = Promise.withResolvers<void>()\n\t\tthis.#ending = ending\n\t\tvoid this.#teardown(ending)\n\t\treturn ending.promise\n\t}\n\n\tasync #handle(input: TInput, execution: QueueExecution): Promise<TResult> {\n\t\tconst token = await this.#pool.acquire(execution.signal)\n\t\ttry {\n\t\t\treturn await this.#handler(input, token.value, execution)\n\t\t} finally {\n\t\t\ttoken.release()\n\t\t}\n\t}\n\n\tasync #teardown(ending: PromiseWithResolvers<void>): Promise<void> {\n\t\tconst failures: unknown[] = []\n\t\ttry {\n\t\t\tawait this.#queue.destroy()\n\t\t} catch (error) {\n\t\t\tfailures.push(error)\n\t\t}\n\t\ttry {\n\t\t\tawait this.#pool.destroy()\n\t\t} catch (error) {\n\t\t\tfailures.push(error)\n\t\t}\n\t\tthis.#emitter.destroy()\n\t\tif (failures.length === 0) ending.resolve()\n\t\telse if (failures.length === 1) ending.reject(failures[0])\n\t\telse ending.reject(new AggregateError(failures, 'worker destroy cleanup failed'))\n\t}\n\n\t// Bridge the inner queue's lifecycle onto the worker's OWN emitter, once at construction.\n\t// Each listener re-emits the queue event directly on the worker's emitter, which isolates a\n\t// worker observer's throw (routing it to the worker's `error` handler). Because the bridge\n\t// listener itself never throws, the queue's own `#emitter.emit` — which invoked this\n\t// listener — sees no throw, so the inner queue's engine stays balanced regardless of what a\n\t// worker observer does. The events are already post-transition (they fire from the queue's\n\t// own post-settle / post-wake emits), so this stays observation.\n\t#bridge(): void {\n\t\tconst queue = this.#queue.emitter\n\t\tqueue.on('enqueue', (id) => this.#emitter.emit('enqueue', id))\n\t\tqueue.on('start', (id) => this.#emitter.emit('start', id))\n\t\tqueue.on('retry', (id, attempt) => this.#emitter.emit('retry', id, attempt))\n\t\tqueue.on('success', (id, result) => this.#emitter.emit('success', id, result))\n\t\tqueue.on('failure', (id, error) => this.#emitter.emit('failure', id, error))\n\t\tqueue.on('abort', (reason) => this.#emitter.emit('abort', reason))\n\t\tqueue.on('drain', () => this.#emitter.emit('drain'))\n\t}\n}\n","import type { WorkerInterface, WorkerOptions } from './types.js'\nimport { Worker } from './Worker.js'\n\n/**\n * Create a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`\n * (`@orkestrel/pool`). Each enqueued input runs through the handler against an\n * automatically acquired pooled resource (released when the job settles), with the\n * queue's bounded concurrency, retries, and per-attempt timeout / abort.\n *\n * @remarks\n * The pool's `max` defaults to `concurrency`, so resources match the jobs in flight and\n * are reused across jobs. A handler that throws still releases its resource (the\n * acquire/release pair brackets the call in a `finally`), so a later job reuses it. The\n * lifecycle (`start` / `stop` / `pause` / `resume` / `abort` / `clear` / `destroy`)\n * delegates to the queue; `destroy` also tears the pool down. Observable (§13): a typed\n * `emitter` surfaces the queue lifecycle (`enqueue` / `start` / `success` / `failure` / …).\n *\n * @typeParam TInput - The work input each job carries\n * @typeParam TResource - The pooled resource each job runs against\n * @typeParam TResult - The value the handler resolves for a job\n * @param options - The `handler` and `pool` plus optional `concurrency` (default `1`),\n * `retries` (default `0`), and a default per-attempt `timeout` in milliseconds\n * @returns A working {@link WorkerInterface}\n *\n * @example\n * ```ts\n * import { createWorker } from '@orkestrel/worker'\n *\n * const worker = createWorker<Query, Connection, Rows>({\n * \tpool: { create: () => connect(), destroy: (connection) => connection.close() },\n * \thandler: (query, connection, { signal }) => connection.run(query, signal),\n * \tconcurrency: 4,\n * \tretries: 1,\n * })\n *\n * const rows = await worker.enqueue(query)\n * ```\n */\nexport function createWorker<TInput, TResource, TResult>(\n\toptions: WorkerOptions<TInput, TResource, TResult>,\n): WorkerInterface<TInput, TResult> {\n\treturn new Worker(options)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,IAAa,SAAb,MAA4F;CAC3F;CACA;CAIA;CACA;CACA;CAEA,YAAY,SAAoD;EAC/D,MAAM,EACL,aAAa,qBACb,SACA,IACA,OACA,SACA,SACA,UACG;EACJ,MAAM,cAAc,wBAAwB,KAAA,IAAY,IAAI;EAC5D,KAAKG,WAAW;EAChB,KAAKD,WAAW,IAAI,mBAAA,QAAiC;GACpD,GAAI,OAAO,KAAA,IAAY,EAAE,GAAG,IAAI,CAAC;GACjC,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACxC,CAAC;EACD,KAAKF,SAAS,IAAI,iBAAA,MAAuB;GACxC,SAAS,KAAKI,QAAQ,KAAK,IAAI;GAC/B;GACA,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC3C,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC3C,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACxC,CAAC;EAED,MAAM,EAAE,KAAK,IAAI,QAAQ,OAAO,WAAW,QAAQ,SAAS,aAD/C,QAAQ;EAErB,KAAKH,QAAQ,IAAI,gBAAA,KAAgB;GAChC;GACA,KAAK,QAAQ,KAAA,IAAY,cAAc;GACvC,GAAI,WAAW,KAAA,IAAY,EAAE,IAAI,OAAO,IAAI,CAAC;GAC7C,GAAI,cAAc,KAAA,IAAY,EAAE,OAAO,UAAU,IAAI,CAAC;GACtD,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;GAC3C,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC9C,CAAC;EACD,KAAKI,QAAQ;CACd;CAEA,IAAI,UAAqD;EACxD,OAAO,KAAKH;CACb;CAEA,IAAI,QAAgB;EACnB,OAAO,KAAKF,OAAO;CACpB;CAEA,IAAI,SAAiB;EACpB,OAAO,KAAKA,OAAO;CACpB;CAEA,IAAI,SAAkB;EACrB,OAAO,KAAKA,OAAO;CACpB;CAEA,IAAI,UAAmB;EACtB,OAAO,KAAKA,OAAO;CACpB;CAEA,QAAQ,OAAe,SAA+C;EACrE,OAAO,KAAKA,OAAO,QAAQ,OAAO,OAAO;CAC1C;CAEA,UAAyB;EACxB,OAAO,KAAKA,OAAO,QAAQ;CAC5B;CAEA,QAAc;EACb,KAAKA,OAAO,MAAM;CACnB;CAEA,OAAsB;EACrB,OAAO,KAAKA,OAAO,KAAK;CACzB;CAEA,QAAc;EACb,KAAKA,OAAO,MAAM;CACnB;CAEA,SAAe;EACd,KAAKA,OAAO,OAAO;CACpB;CAEA,MAAM,QAAiC;EACtC,OAAO,KAAKA,OAAO,MAAM,MAAM;CAChC;CAEA,QAAuB;EACtB,OAAO,KAAKA,OAAO,MAAM;CAC1B;CAEA,UAAyB;EACxB,IAAI,KAAKM,YAAY,KAAA,GAAW,OAAO,KAAKA,QAAQ;EACpD,MAAM,SAAS,QAAQ,cAAoB;EAC3C,KAAKA,UAAU;EACf,KAAUC,UAAU,MAAM;EAC1B,OAAO,OAAO;CACf;CAEA,MAAMH,QAAQ,OAAe,WAA6C;EACzE,MAAM,QAAQ,MAAM,KAAKH,MAAM,QAAQ,UAAU,MAAM;EACvD,IAAI;GACH,OAAO,MAAM,KAAKE,SAAS,OAAO,MAAM,OAAO,SAAS;EACzD,UAAU;GACT,MAAM,QAAQ;EACf;CACD;CAEA,MAAMI,UAAU,QAAmD;EAClE,MAAM,WAAsB,CAAC;EAC7B,IAAI;GACH,MAAM,KAAKP,OAAO,QAAQ;EAC3B,SAAS,OAAO;GACf,SAAS,KAAK,KAAK;EACpB;EACA,IAAI;GACH,MAAM,KAAKC,MAAM,QAAQ;EAC1B,SAAS,OAAO;GACf,SAAS,KAAK,KAAK;EACpB;EACA,KAAKC,SAAS,QAAQ;EACtB,IAAI,SAAS,WAAW,GAAG,OAAO,QAAQ;OACrC,IAAI,SAAS,WAAW,GAAG,OAAO,OAAO,SAAS,EAAE;OACpD,OAAO,OAAO,IAAI,eAAe,UAAU,+BAA+B,CAAC;CACjF;CASA,UAAgB;EACf,MAAM,QAAQ,KAAKF,OAAO;EAC1B,MAAM,GAAG,YAAY,OAAO,KAAKE,SAAS,KAAK,WAAW,EAAE,CAAC;EAC7D,MAAM,GAAG,UAAU,OAAO,KAAKA,SAAS,KAAK,SAAS,EAAE,CAAC;EACzD,MAAM,GAAG,UAAU,IAAI,YAAY,KAAKA,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC;EAC3E,MAAM,GAAG,YAAY,IAAI,WAAW,KAAKA,SAAS,KAAK,WAAW,IAAI,MAAM,CAAC;EAC7E,MAAM,GAAG,YAAY,IAAI,UAAU,KAAKA,SAAS,KAAK,WAAW,IAAI,KAAK,CAAC;EAC3E,MAAM,GAAG,UAAU,WAAW,KAAKA,SAAS,KAAK,SAAS,MAAM,CAAC;EACjE,MAAM,GAAG,eAAe,KAAKA,SAAS,KAAK,OAAO,CAAC;CACpD;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9JA,SAAgB,aACf,SACmC;CACnC,OAAO,IAAI,OAAO,OAAO;AAC1B"}
1
+ {"version":3,"file":"index.cjs","names":["#queue","#pool","#emitter","#handler","#handle","#bridge","#ending","#teardown"],"sources":["../../../src/core/Worker.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { EmitterInterface } from '@orkestrel/emitter'\nimport type { QueueContext, QueueEntryOptions } from '@orkestrel/queue'\nimport type { WorkerEventMap, WorkerHandler, WorkerInterface, WorkerOptions } from './types.js'\nimport { Emitter } from '@orkestrel/emitter'\nimport { Pool } from '@orkestrel/pool'\nimport { Queue } from '@orkestrel/queue'\n\n/**\n * Represents a resource-backed job worker — a thin facade composing a `Queue`\n * (`@orkestrel/queue`) with a `Pool` (`@orkestrel/pool`).\n *\n * @remarks\n * - **Composition, not reimplementation.** The Worker owns a `Pool` (built from\n * `options.pool`) and a `Queue` whose handler ACQUIRES a pooled resource, runs the\n * user handler against it, and RELEASES it in a `finally`. All concurrency, retries,\n * timeout, and lifecycle are the Queue's — the Worker adds only the resource pairing.\n * - **Resource ↔ concurrency.** The queue strictly validates `concurrency` as a positive\n * safe integer after caller options are captured once. Only `undefined` defaults\n * `concurrency` to `1` or pool `max` to that value; runtime `null` reaches the owning\n * validator. The queue validates before the pool option is read; every declared pool member\n * is then captured once by direct access, preserving inherited and non-enumerable structural\n * options. At most one resource exists per in-flight job by default, and idle resources are\n * reused across jobs.\n * - **Acquire over the attempt signal.** Each job acquires using the attempt's\n * `context.signal`, so an `abort` / `timeout` while waiting for a resource rejects\n * the acquire — the Queue then handles retry / rejection, and there is no token to\n * release (the resource was never leased).\n * - **Lifecycle (§10).** `enqueue` / `restore` / `start` / `stop` / `pause` / `resume` /\n * `abort` / `clear` delegate to the queue; `count` / `active` / `paused` / `stopped`\n * read it. `stop` / `abort` / `clear` return the queue's own cleanup barriers.\n * `destroy` returns one stable barrier while it tears down the queue, then the pool,\n * and destroys the worker emitter last. A sole cleanup failure is preserved by\n * identity; failures from both layers become an ordered `AggregateError`.\n * - **Durability.** An optional `store` is passed straight through to the queue, so the\n * worker's outstanding jobs persist; `restore` re-runs them (delegated to the queue).\n * - **Observable (§13).** The owned {@link emitter} ({@link WorkerEventMap}) RE-EXPOSES the\n * underlying queue's job lifecycle (`enqueue` / `start` / `retry` / `success` / `failure` /\n * `abort` / `drain`) as the worker's OWN events — bridged from the inner queue's emitter at\n * construction — so a consumer observes the worker without reaching through to internals.\n * The bridge re-emits directly on the worker's own emitter; the worker emitter isolates a\n * listener throw and routes it to its `error` handler (the `error` option), so a buggy\n * worker observer can never corrupt the inner queue or pool — the bridge listener never\n * throws, so the inner queue's own emit stays balanced. The pool's create / acquire /\n * release events stay the pool's internal concern (a Worker manages its own resources);\n * observe a `Pool` directly for those.\n */\nexport class Worker<TInput, TResource, TResult> implements WorkerInterface<TInput, TResult> {\n\treadonly #queue: Queue<TInput, TResult>\n\treadonly #pool: Pool<TResource>\n\t// The PUSH observation surface (§13) — the worker's OWN emitter, fed by the queue→worker\n\t// bridge. The emitter isolates a worker observer's throw (routing it to the `error`\n\t// handler), so it never escapes into queue or pool.\n\treadonly #emitter: Emitter<WorkerEventMap<TResult>>\n\treadonly #handler: WorkerHandler<TInput, TResource, TResult>\n\t#ending: PromiseWithResolvers<void> | undefined\n\n\tconstructor(options: WorkerOptions<TInput, TResource, TResult>) {\n\t\tconst {\n\t\t\tconcurrency: capturedConcurrency,\n\t\t\thandler,\n\t\t\ton,\n\t\t\terror,\n\t\t\tretries,\n\t\t\ttimeout,\n\t\t\tstore,\n\t\t} = options\n\t\tconst concurrency = capturedConcurrency === undefined ? 1 : capturedConcurrency\n\t\tthis.#handler = handler\n\t\tthis.#emitter = new Emitter<WorkerEventMap<TResult>>({\n\t\t\t...(on !== undefined ? { on } : {}),\n\t\t\t...(error !== undefined ? { error } : {}),\n\t\t})\n\t\tthis.#queue = new Queue<TInput, TResult>({\n\t\t\thandler: this.#handle.bind(this),\n\t\t\tconcurrency,\n\t\t\t...(retries !== undefined ? { retries } : {}),\n\t\t\t...(timeout !== undefined ? { timeout } : {}),\n\t\t\t...(store !== undefined ? { store } : {}),\n\t\t})\n\t\tconst pool = options.pool\n\t\tconst { max, on: poolOn, error: poolError, create, destroy, validate } = pool\n\t\tthis.#pool = new Pool<TResource>({\n\t\t\tcreate,\n\t\t\tmax: max === undefined ? concurrency : max,\n\t\t\t...(poolOn !== undefined ? { on: poolOn } : {}),\n\t\t\t...(poolError !== undefined ? { error: poolError } : {}),\n\t\t\t...(destroy !== undefined ? { destroy } : {}),\n\t\t\t...(validate !== undefined ? { validate } : {}),\n\t\t})\n\t\tthis.#bridge()\n\t}\n\n\tget emitter(): EmitterInterface<WorkerEventMap<TResult>> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#queue.count\n\t}\n\n\tget active(): number {\n\t\treturn this.#queue.active\n\t}\n\n\tget paused(): boolean {\n\t\treturn this.#queue.paused\n\t}\n\n\tget stopped(): boolean {\n\t\treturn this.#queue.stopped\n\t}\n\n\tenqueue(input: TInput, options?: QueueEntryOptions): Promise<TResult> {\n\t\treturn this.#queue.enqueue(input, options)\n\t}\n\n\trestore(): Promise<void> {\n\t\treturn this.#queue.restore()\n\t}\n\n\tstart(): void {\n\t\tthis.#queue.start()\n\t}\n\n\tstop(): Promise<void> {\n\t\treturn this.#queue.stop()\n\t}\n\n\tpause(): void {\n\t\tthis.#queue.pause()\n\t}\n\n\tresume(): void {\n\t\tthis.#queue.resume()\n\t}\n\n\tabort(reason?: unknown): Promise<void> {\n\t\treturn this.#queue.abort(reason)\n\t}\n\n\tclear(): Promise<void> {\n\t\treturn this.#queue.clear()\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tif (this.#ending !== undefined) return this.#ending.promise\n\t\tconst ending = Promise.withResolvers<void>()\n\t\tthis.#ending = ending\n\t\tvoid this.#teardown(ending)\n\t\treturn ending.promise\n\t}\n\n\tasync #handle(input: TInput, context: QueueContext): Promise<TResult> {\n\t\tconst token = await this.#pool.acquire(context.signal)\n\t\ttry {\n\t\t\treturn await this.#handler(input, token.value, context)\n\t\t} finally {\n\t\t\ttoken.release()\n\t\t}\n\t}\n\n\tasync #teardown(ending: PromiseWithResolvers<void>): Promise<void> {\n\t\tconst failures: unknown[] = []\n\t\ttry {\n\t\t\tawait this.#queue.destroy()\n\t\t} catch (error) {\n\t\t\tfailures.push(error)\n\t\t}\n\t\ttry {\n\t\t\tawait this.#pool.destroy()\n\t\t} catch (error) {\n\t\t\tfailures.push(error)\n\t\t}\n\t\tthis.#emitter.destroy()\n\t\tif (failures.length === 0) ending.resolve()\n\t\telse if (failures.length === 1) ending.reject(failures[0])\n\t\telse ending.reject(new AggregateError(failures, 'worker destroy cleanup failed'))\n\t}\n\n\t// Bridge the inner queue's lifecycle onto the worker's OWN emitter, once at construction.\n\t// Each listener re-emits the queue event directly on the worker's emitter, which isolates a\n\t// worker observer's throw (routing it to the worker's `error` handler). Because the bridge\n\t// listener itself never throws, the queue's own `#emitter.emit` — which invoked this\n\t// listener — sees no throw, so the inner queue's engine stays balanced regardless of what a\n\t// worker observer does. The events are already post-transition (they fire from the queue's\n\t// own post-settle / post-wake emits), so this stays observation.\n\t#bridge(): void {\n\t\tconst queue = this.#queue.emitter\n\t\tqueue.on('enqueue', (id) => this.#emitter.emit('enqueue', id))\n\t\tqueue.on('start', (id) => this.#emitter.emit('start', id))\n\t\tqueue.on('retry', (id, attempt) => this.#emitter.emit('retry', id, attempt))\n\t\tqueue.on('success', (id, result) => this.#emitter.emit('success', id, result))\n\t\tqueue.on('failure', (id, error) => this.#emitter.emit('failure', id, error))\n\t\tqueue.on('abort', (reason) => this.#emitter.emit('abort', reason))\n\t\tqueue.on('drain', () => this.#emitter.emit('drain'))\n\t}\n}\n","import type { WorkerInterface, WorkerOptions } from './types.js'\nimport { Worker } from './Worker.js'\n\n/**\n * Creates a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`\n * (`@orkestrel/pool`). Each enqueued input runs through the handler against an\n * automatically acquired pooled resource (released when the job settles), with the\n * queue's bounded concurrency, retries, and per-attempt timeout / abort.\n *\n * @remarks\n * Default for the pool's `max`: the `concurrency` value, so resources match the jobs in flight.\n * Resources are reused across jobs. A handler that throws still releases its resource (the\n * acquire/release pair brackets the call in a `finally`), so a later job reuses it. The\n * lifecycle (`start` / `stop` / `pause` / `resume` / `abort` / `clear` / `destroy`)\n * delegates to the queue; `destroy` also tears the pool down. Observable (§13): a typed\n * `emitter` surfaces the queue lifecycle (`enqueue` / `start` / `success` / `failure` / …).\n *\n * @typeParam TInput - The work input each job carries\n * @typeParam TResource - The pooled resource each job runs against\n * @typeParam TResult - The value the handler resolves for a job\n * @param options - The `handler` and `pool` plus the optional `concurrency`, `retries`,\n * `timeout`, `store`, `on`, and `error` keys (see {@link WorkerOptions})\n * @returns A working {@link WorkerInterface}\n *\n * @example\n * ```ts\n * import { createWorker } from '@orkestrel/worker'\n *\n * const worker = createWorker<Query, Connection, Rows>({\n * \tpool: { create: () => connect(), destroy: (connection) => connection.close() },\n * \thandler: (query, connection, { signal }) => connection.run(query, signal),\n * \tconcurrency: 4,\n * \tretries: 1,\n * })\n *\n * const rows = await worker.enqueue(query)\n * ```\n */\nexport function createWorker<TInput, TResource, TResult>(\n\toptions: WorkerOptions<TInput, TResource, TResult>,\n): WorkerInterface<TInput, TResult> {\n\treturn new Worker(options)\n}\n"],"mappings":"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"}
@@ -2,19 +2,19 @@ import { EmitterErrorHandler } from '@orkestrel/emitter';
2
2
  import { EmitterHooks } from '@orkestrel/emitter';
3
3
  import { EmitterInterface } from '@orkestrel/emitter';
4
4
  import { PoolOptions } from '@orkestrel/pool';
5
+ import { QueueContext } from '@orkestrel/queue';
5
6
  import { QueueEntryOptions } from '@orkestrel/queue';
6
- import { QueueExecution } from '@orkestrel/queue';
7
7
  import { QueueStoreInterface } from '@orkestrel/queue';
8
8
 
9
9
  /**
10
- * Create a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
10
+ * Creates a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
11
11
  * (`@orkestrel/pool`). Each enqueued input runs through the handler against an
12
12
  * automatically acquired pooled resource (released when the job settles), with the
13
13
  * queue's bounded concurrency, retries, and per-attempt timeout / abort.
14
14
  *
15
15
  * @remarks
16
- * The pool's `max` defaults to `concurrency`, so resources match the jobs in flight and
17
- * are reused across jobs. A handler that throws still releases its resource (the
16
+ * Default for the pool's `max`: the `concurrency` value, so resources match the jobs in flight.
17
+ * Resources are reused across jobs. A handler that throws still releases its resource (the
18
18
  * acquire/release pair brackets the call in a `finally`), so a later job reuses it. The
19
19
  * lifecycle (`start` / `stop` / `pause` / `resume` / `abort` / `clear` / `destroy`)
20
20
  * delegates to the queue; `destroy` also tears the pool down. Observable (§13): a typed
@@ -23,8 +23,8 @@ import { QueueStoreInterface } from '@orkestrel/queue';
23
23
  * @typeParam TInput - The work input each job carries
24
24
  * @typeParam TResource - The pooled resource each job runs against
25
25
  * @typeParam TResult - The value the handler resolves for a job
26
- * @param options - The `handler` and `pool` plus optional `concurrency` (default `1`),
27
- * `retries` (default `0`), and a default per-attempt `timeout` in milliseconds
26
+ * @param options - The `handler` and `pool` plus the optional `concurrency`, `retries`,
27
+ * `timeout`, `store`, `on`, and `error` keys (see {@link WorkerOptions})
28
28
  * @returns A working {@link WorkerInterface}
29
29
  *
30
30
  * @example
@@ -44,8 +44,8 @@ import { QueueStoreInterface } from '@orkestrel/queue';
44
44
  export declare function createWorker<TInput, TResource, TResult>(options: WorkerOptions_2<TInput, TResource, TResult>): WorkerInterface<TInput, TResult>;
45
45
 
46
46
  /**
47
- * A resource-backed job worker — a thin facade composing a `Queue` (`@orkestrel/queue`)
48
- * with a `Pool` (`@orkestrel/pool`).
47
+ * Represents a resource-backed job worker — a thin facade composing a `Queue`
48
+ * (`@orkestrel/queue`) with a `Pool` (`@orkestrel/pool`).
49
49
  *
50
50
  * @remarks
51
51
  * - **Composition, not reimplementation.** The Worker owns a `Pool` (built from
@@ -60,7 +60,7 @@ export declare function createWorker<TInput, TResource, TResult>(options: Worker
60
60
  * options. At most one resource exists per in-flight job by default, and idle resources are
61
61
  * reused across jobs.
62
62
  * - **Acquire over the attempt signal.** Each job acquires using the attempt's
63
- * `execution.signal`, so an `abort` / `timeout` while waiting for a resource rejects
63
+ * `context.signal`, so an `abort` / `timeout` while waiting for a resource rejects
64
64
  * the acquire — the Queue then handles retry / rejection, and there is no token to
65
65
  * release (the resource was never leased).
66
66
  * - **Lifecycle (§10).** `enqueue` / `restore` / `start` / `stop` / `pause` / `resume` /
@@ -103,7 +103,7 @@ declare class Worker_2<TInput, TResource, TResult> implements WorkerInterface<TI
103
103
  export { Worker_2 as Worker }
104
104
 
105
105
  /**
106
- * The push observation surface of a {@link WorkerInterface} (AGENTS §13) — the job
106
+ * Represents the push observation surface of a {@link WorkerInterface} — the job
107
107
  * lifecycle a fire-and-forget observer subscribes to, surfacing the underlying queue's
108
108
  * moments so a Worker consumer never reaches through to the internal `Queue`.
109
109
  *
@@ -115,37 +115,37 @@ export { Worker_2 as Worker }
115
115
  * map RE-EXPOSES the queue lifecycle the worker surfaces (`enqueue` / `start` / `retry` /
116
116
  * `success` / `failure` / `abort` / `drain`) as the worker's OWN events — wired from the
117
117
  * underlying queue's emitter at construction, so a buggy observer is isolated exactly as
118
- * on the queue (a throw routes to the worker emitter's `error` handler, AGENTS §13). The
118
+ * on the queue (a throw routes to the worker emitter's `error` handler). The
119
119
  * pool's create / acquire / release events stay the pool's internal concern (a Worker
120
120
  * manages its own resources); a consumer who wants them observes a `Pool` directly.
121
121
  * Declared as a `type` alias (§4.5).
122
122
  */
123
123
  declare type WorkerEventMap_2<TResult> = {
124
- /** A job was accepted — its id (delegated from the underlying queue's `enqueue`). */
124
+ /** Fires when a job is accepted — its id (delegated from the underlying queue's `enqueue`). */
125
125
  readonly enqueue: readonly [id: string];
126
- /** A job's attempt began running — its id. */
126
+ /** Fires when a job's attempt begins running — its id. */
127
127
  readonly start: readonly [id: string];
128
- /** A failed job attempt is being retried — its id + the next (1-based) attempt index. */
128
+ /** Fires when a failed job attempt is being retried — its id + the next (1-based) attempt index. */
129
129
  readonly retry: readonly [id: string, attempt: number];
130
- /** A job settled successfully — its id + the resolved result. */
130
+ /** Fires when a job settles successfully — its id + the resolved result. */
131
131
  readonly success: readonly [id: string, result: TResult];
132
- /** A job settled with a terminal failure — its id + the error. */
132
+ /** Fires when a job settles with a terminal failure — its id + the error. */
133
133
  readonly failure: readonly [id: string, error: unknown];
134
- /** The worker was aborted — the queue's coded abort error retaining the caller reason. */
134
+ /** Fires when the worker is aborted — the queue's coded abort error retaining the caller reason. */
135
135
  readonly abort: readonly [reason: unknown];
136
- /** The worker went idle — no pending jobs and none in flight. */
136
+ /** Fires when the worker goes idle — no pending jobs and none in flight. */
137
137
  readonly drain: readonly [];
138
138
  };
139
139
  export { WorkerEventMap_2 as WorkerEventMap }
140
140
 
141
141
  /** Runs one worker job with a leased pool resource. */
142
- export declare type WorkerHandler<TInput, TResource, TResult> = (input: TInput, resource: TResource, execution: QueueExecution) => Promise<TResult> | TResult;
142
+ export declare type WorkerHandler<TInput, TResource, TResult> = (input: TInput, resource: TResource, context: QueueContext) => Promise<TResult> | TResult;
143
143
 
144
144
  /**
145
- * A resource-backed job worker — a Queue whose handler runs against a pooled resource.
145
+ * Represents a resource-backed job worker — a Queue whose handler runs against a pooled resource.
146
146
  *
147
147
  * @remarks
148
- * Exposes a typed {@link emitter} (AGENTS §13) carrying the job lifecycle
148
+ * Exposes a typed {@link emitter} carrying the job lifecycle
149
149
  * ({@link WorkerEventMap}) — the underlying queue's moments re-exposed as the worker's own,
150
150
  * so a consumer never reaches through to internals. Emitting is observation-only: a buggy
151
151
  * observer is isolated exactly as on the queue (a throw routes to the emitter's `error`
@@ -158,24 +158,24 @@ export declare interface WorkerInterface<TInput, TResult> {
158
158
  readonly paused: boolean;
159
159
  readonly stopped: boolean;
160
160
  enqueue(input: TInput, options?: QueueEntryOptions): Promise<TResult>;
161
- /** Re-enqueue outstanding entries loaded from the store; no-op without a store. */
161
+ /** Re-enqueues outstanding entries loaded from the store; no-op without a store. */
162
162
  restore(): Promise<void>;
163
163
  start(): void;
164
- /** Stop the queue and await current-loop and durable cleanup quiescence. */
164
+ /** Stops the queue and awaits current-loop and durable cleanup quiescence. */
165
165
  stop(): Promise<void>;
166
166
  pause(): void;
167
167
  resume(): void;
168
168
  /**
169
- * Cancel in-flight work, reject pending work, and await queue-owned cleanup.
169
+ * Cancels in-flight work, rejects pending work, and awaits queue-owned cleanup.
170
170
  *
171
171
  * @param reason - Optional cause retained by the queue's coded abort error
172
172
  * @returns The underlying queue's stable abort barrier
173
173
  */
174
174
  abort(reason?: unknown): Promise<void>;
175
- /** Drop pending work and await its durable cleanup. */
175
+ /** Drops pending work and awaits its durable cleanup. */
176
176
  clear(): Promise<void>;
177
177
  /**
178
- * Tear down the queue, then the pool, and finally the worker emitter.
178
+ * Tears down the queue, then the pool, and finally the worker emitter.
179
179
  *
180
180
  * @returns One stable barrier shared by every call; it rejects with the original sole
181
181
  * cleanup failure or an ordered `AggregateError` when both queue and pool fail
@@ -184,17 +184,18 @@ export declare interface WorkerInterface<TInput, TResult> {
184
184
  }
185
185
 
186
186
  /**
187
- * Options for `createWorker`.
187
+ * Configures `createWorker`.
188
188
  *
189
189
  * @remarks
190
190
  * - `handler` — runs each job against an acquired pool resource; rejecting triggers a
191
191
  * retry while attempts remain (delegated to the underlying queue).
192
- * - `pool` — the {@link PoolOptions} for the resource the handler runs against; its
193
- * `max` defaults to `concurrency` so resources match the jobs in flight.
194
- * - `concurrency` — the maximum jobs in flight at once; defaults to `1` and must be a
195
- * positive safe integer, as validated by the underlying queue.
196
- * - `retries` — the default extra attempts per job on failure; defaults to `0`.
197
- * - `timeout` — the default per-attempt deadline in milliseconds; defaults to none.
192
+ * - `pool` — the {@link PoolOptions} for the resource the handler runs against, sized so
193
+ * resources match the jobs in flight. Default for its `max`: the `concurrency` value.
194
+ * - `concurrency` — the maximum jobs in flight at once; it must be a positive safe
195
+ * integer, as validated by the underlying queue. Default: 1.
196
+ * - `retries` — the default extra attempts per job on failure. Default: 0.
197
+ * - `timeout` — the default per-attempt deadline in milliseconds. Default: no per-attempt
198
+ * deadline.
198
199
  * - `store` — durable backing; outstanding entries survive a restart; call
199
200
  * `restore()` to re-run them.
200
201
  * - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the worker's
@@ -203,13 +204,13 @@ export declare interface WorkerInterface<TInput, TResult> {
203
204
  */
204
205
  declare interface WorkerOptions_2<TInput, TResource, TResult> {
205
206
  readonly on?: EmitterHooks<WorkerEventMap_2<TResult>>;
206
- /** The emitter's listener-error handler (AGENTS §13) — a listener throw routes here, not to a domain event. */
207
+ /** Holds the emitter's listener-error handler; a listener throw routes here, not to a domain event. */
207
208
  readonly error?: EmitterErrorHandler;
208
209
  readonly handler: WorkerHandler<TInput, TResource, TResult>;
209
210
  readonly pool: PoolOptions<TResource>;
210
211
  readonly concurrency?: number;
211
212
  readonly retries?: number;
212
- /** Integer milliseconds in `0..2_147_483_647`; `0` disables the per-attempt deadline. */
213
+ /** Holds integer milliseconds in `0..2_147_483_647`; `0` disables the per-attempt deadline. */
213
214
  readonly timeout?: number;
214
215
  readonly store?: QueueStoreInterface<TInput>;
215
216
  }
@@ -2,19 +2,19 @@ import { EmitterErrorHandler } from '@orkestrel/emitter';
2
2
  import { EmitterHooks } from '@orkestrel/emitter';
3
3
  import { EmitterInterface } from '@orkestrel/emitter';
4
4
  import { PoolOptions } from '@orkestrel/pool';
5
+ import { QueueContext } from '@orkestrel/queue';
5
6
  import { QueueEntryOptions } from '@orkestrel/queue';
6
- import { QueueExecution } from '@orkestrel/queue';
7
7
  import { QueueStoreInterface } from '@orkestrel/queue';
8
8
 
9
9
  /**
10
- * Create a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
10
+ * Creates a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
11
11
  * (`@orkestrel/pool`). Each enqueued input runs through the handler against an
12
12
  * automatically acquired pooled resource (released when the job settles), with the
13
13
  * queue's bounded concurrency, retries, and per-attempt timeout / abort.
14
14
  *
15
15
  * @remarks
16
- * The pool's `max` defaults to `concurrency`, so resources match the jobs in flight and
17
- * are reused across jobs. A handler that throws still releases its resource (the
16
+ * Default for the pool's `max`: the `concurrency` value, so resources match the jobs in flight.
17
+ * Resources are reused across jobs. A handler that throws still releases its resource (the
18
18
  * acquire/release pair brackets the call in a `finally`), so a later job reuses it. The
19
19
  * lifecycle (`start` / `stop` / `pause` / `resume` / `abort` / `clear` / `destroy`)
20
20
  * delegates to the queue; `destroy` also tears the pool down. Observable (§13): a typed
@@ -23,8 +23,8 @@ import { QueueStoreInterface } from '@orkestrel/queue';
23
23
  * @typeParam TInput - The work input each job carries
24
24
  * @typeParam TResource - The pooled resource each job runs against
25
25
  * @typeParam TResult - The value the handler resolves for a job
26
- * @param options - The `handler` and `pool` plus optional `concurrency` (default `1`),
27
- * `retries` (default `0`), and a default per-attempt `timeout` in milliseconds
26
+ * @param options - The `handler` and `pool` plus the optional `concurrency`, `retries`,
27
+ * `timeout`, `store`, `on`, and `error` keys (see {@link WorkerOptions})
28
28
  * @returns A working {@link WorkerInterface}
29
29
  *
30
30
  * @example
@@ -44,8 +44,8 @@ import { QueueStoreInterface } from '@orkestrel/queue';
44
44
  export declare function createWorker<TInput, TResource, TResult>(options: WorkerOptions_2<TInput, TResource, TResult>): WorkerInterface<TInput, TResult>;
45
45
 
46
46
  /**
47
- * A resource-backed job worker — a thin facade composing a `Queue` (`@orkestrel/queue`)
48
- * with a `Pool` (`@orkestrel/pool`).
47
+ * Represents a resource-backed job worker — a thin facade composing a `Queue`
48
+ * (`@orkestrel/queue`) with a `Pool` (`@orkestrel/pool`).
49
49
  *
50
50
  * @remarks
51
51
  * - **Composition, not reimplementation.** The Worker owns a `Pool` (built from
@@ -60,7 +60,7 @@ export declare function createWorker<TInput, TResource, TResult>(options: Worker
60
60
  * options. At most one resource exists per in-flight job by default, and idle resources are
61
61
  * reused across jobs.
62
62
  * - **Acquire over the attempt signal.** Each job acquires using the attempt's
63
- * `execution.signal`, so an `abort` / `timeout` while waiting for a resource rejects
63
+ * `context.signal`, so an `abort` / `timeout` while waiting for a resource rejects
64
64
  * the acquire — the Queue then handles retry / rejection, and there is no token to
65
65
  * release (the resource was never leased).
66
66
  * - **Lifecycle (§10).** `enqueue` / `restore` / `start` / `stop` / `pause` / `resume` /
@@ -103,7 +103,7 @@ declare class Worker_2<TInput, TResource, TResult> implements WorkerInterface<TI
103
103
  export { Worker_2 as Worker }
104
104
 
105
105
  /**
106
- * The push observation surface of a {@link WorkerInterface} (AGENTS §13) — the job
106
+ * Represents the push observation surface of a {@link WorkerInterface} — the job
107
107
  * lifecycle a fire-and-forget observer subscribes to, surfacing the underlying queue's
108
108
  * moments so a Worker consumer never reaches through to the internal `Queue`.
109
109
  *
@@ -115,37 +115,37 @@ export { Worker_2 as Worker }
115
115
  * map RE-EXPOSES the queue lifecycle the worker surfaces (`enqueue` / `start` / `retry` /
116
116
  * `success` / `failure` / `abort` / `drain`) as the worker's OWN events — wired from the
117
117
  * underlying queue's emitter at construction, so a buggy observer is isolated exactly as
118
- * on the queue (a throw routes to the worker emitter's `error` handler, AGENTS §13). The
118
+ * on the queue (a throw routes to the worker emitter's `error` handler). The
119
119
  * pool's create / acquire / release events stay the pool's internal concern (a Worker
120
120
  * manages its own resources); a consumer who wants them observes a `Pool` directly.
121
121
  * Declared as a `type` alias (§4.5).
122
122
  */
123
123
  declare type WorkerEventMap_2<TResult> = {
124
- /** A job was accepted — its id (delegated from the underlying queue's `enqueue`). */
124
+ /** Fires when a job is accepted — its id (delegated from the underlying queue's `enqueue`). */
125
125
  readonly enqueue: readonly [id: string];
126
- /** A job's attempt began running — its id. */
126
+ /** Fires when a job's attempt begins running — its id. */
127
127
  readonly start: readonly [id: string];
128
- /** A failed job attempt is being retried — its id + the next (1-based) attempt index. */
128
+ /** Fires when a failed job attempt is being retried — its id + the next (1-based) attempt index. */
129
129
  readonly retry: readonly [id: string, attempt: number];
130
- /** A job settled successfully — its id + the resolved result. */
130
+ /** Fires when a job settles successfully — its id + the resolved result. */
131
131
  readonly success: readonly [id: string, result: TResult];
132
- /** A job settled with a terminal failure — its id + the error. */
132
+ /** Fires when a job settles with a terminal failure — its id + the error. */
133
133
  readonly failure: readonly [id: string, error: unknown];
134
- /** The worker was aborted — the queue's coded abort error retaining the caller reason. */
134
+ /** Fires when the worker is aborted — the queue's coded abort error retaining the caller reason. */
135
135
  readonly abort: readonly [reason: unknown];
136
- /** The worker went idle — no pending jobs and none in flight. */
136
+ /** Fires when the worker goes idle — no pending jobs and none in flight. */
137
137
  readonly drain: readonly [];
138
138
  };
139
139
  export { WorkerEventMap_2 as WorkerEventMap }
140
140
 
141
141
  /** Runs one worker job with a leased pool resource. */
142
- export declare type WorkerHandler<TInput, TResource, TResult> = (input: TInput, resource: TResource, execution: QueueExecution) => Promise<TResult> | TResult;
142
+ export declare type WorkerHandler<TInput, TResource, TResult> = (input: TInput, resource: TResource, context: QueueContext) => Promise<TResult> | TResult;
143
143
 
144
144
  /**
145
- * A resource-backed job worker — a Queue whose handler runs against a pooled resource.
145
+ * Represents a resource-backed job worker — a Queue whose handler runs against a pooled resource.
146
146
  *
147
147
  * @remarks
148
- * Exposes a typed {@link emitter} (AGENTS §13) carrying the job lifecycle
148
+ * Exposes a typed {@link emitter} carrying the job lifecycle
149
149
  * ({@link WorkerEventMap}) — the underlying queue's moments re-exposed as the worker's own,
150
150
  * so a consumer never reaches through to internals. Emitting is observation-only: a buggy
151
151
  * observer is isolated exactly as on the queue (a throw routes to the emitter's `error`
@@ -158,24 +158,24 @@ export declare interface WorkerInterface<TInput, TResult> {
158
158
  readonly paused: boolean;
159
159
  readonly stopped: boolean;
160
160
  enqueue(input: TInput, options?: QueueEntryOptions): Promise<TResult>;
161
- /** Re-enqueue outstanding entries loaded from the store; no-op without a store. */
161
+ /** Re-enqueues outstanding entries loaded from the store; no-op without a store. */
162
162
  restore(): Promise<void>;
163
163
  start(): void;
164
- /** Stop the queue and await current-loop and durable cleanup quiescence. */
164
+ /** Stops the queue and awaits current-loop and durable cleanup quiescence. */
165
165
  stop(): Promise<void>;
166
166
  pause(): void;
167
167
  resume(): void;
168
168
  /**
169
- * Cancel in-flight work, reject pending work, and await queue-owned cleanup.
169
+ * Cancels in-flight work, rejects pending work, and awaits queue-owned cleanup.
170
170
  *
171
171
  * @param reason - Optional cause retained by the queue's coded abort error
172
172
  * @returns The underlying queue's stable abort barrier
173
173
  */
174
174
  abort(reason?: unknown): Promise<void>;
175
- /** Drop pending work and await its durable cleanup. */
175
+ /** Drops pending work and awaits its durable cleanup. */
176
176
  clear(): Promise<void>;
177
177
  /**
178
- * Tear down the queue, then the pool, and finally the worker emitter.
178
+ * Tears down the queue, then the pool, and finally the worker emitter.
179
179
  *
180
180
  * @returns One stable barrier shared by every call; it rejects with the original sole
181
181
  * cleanup failure or an ordered `AggregateError` when both queue and pool fail
@@ -184,17 +184,18 @@ export declare interface WorkerInterface<TInput, TResult> {
184
184
  }
185
185
 
186
186
  /**
187
- * Options for `createWorker`.
187
+ * Configures `createWorker`.
188
188
  *
189
189
  * @remarks
190
190
  * - `handler` — runs each job against an acquired pool resource; rejecting triggers a
191
191
  * retry while attempts remain (delegated to the underlying queue).
192
- * - `pool` — the {@link PoolOptions} for the resource the handler runs against; its
193
- * `max` defaults to `concurrency` so resources match the jobs in flight.
194
- * - `concurrency` — the maximum jobs in flight at once; defaults to `1` and must be a
195
- * positive safe integer, as validated by the underlying queue.
196
- * - `retries` — the default extra attempts per job on failure; defaults to `0`.
197
- * - `timeout` — the default per-attempt deadline in milliseconds; defaults to none.
192
+ * - `pool` — the {@link PoolOptions} for the resource the handler runs against, sized so
193
+ * resources match the jobs in flight. Default for its `max`: the `concurrency` value.
194
+ * - `concurrency` — the maximum jobs in flight at once; it must be a positive safe
195
+ * integer, as validated by the underlying queue. Default: 1.
196
+ * - `retries` — the default extra attempts per job on failure. Default: 0.
197
+ * - `timeout` — the default per-attempt deadline in milliseconds. Default: no per-attempt
198
+ * deadline.
198
199
  * - `store` — durable backing; outstanding entries survive a restart; call
199
200
  * `restore()` to re-run them.
200
201
  * - `on` — the reserved {@link EmitterHooks} key (§8): initial listeners for the worker's
@@ -203,13 +204,13 @@ export declare interface WorkerInterface<TInput, TResult> {
203
204
  */
204
205
  declare interface WorkerOptions_2<TInput, TResource, TResult> {
205
206
  readonly on?: EmitterHooks<WorkerEventMap_2<TResult>>;
206
- /** The emitter's listener-error handler (AGENTS §13) — a listener throw routes here, not to a domain event. */
207
+ /** Holds the emitter's listener-error handler; a listener throw routes here, not to a domain event. */
207
208
  readonly error?: EmitterErrorHandler;
208
209
  readonly handler: WorkerHandler<TInput, TResource, TResult>;
209
210
  readonly pool: PoolOptions<TResource>;
210
211
  readonly concurrency?: number;
211
212
  readonly retries?: number;
212
- /** Integer milliseconds in `0..2_147_483_647`; `0` disables the per-attempt deadline. */
213
+ /** Holds integer milliseconds in `0..2_147_483_647`; `0` disables the per-attempt deadline. */
213
214
  readonly timeout?: number;
214
215
  readonly store?: QueueStoreInterface<TInput>;
215
216
  }
@@ -3,8 +3,8 @@ import { Pool } from "@orkestrel/pool";
3
3
  import { Queue } from "@orkestrel/queue";
4
4
  //#region src/core/Worker.ts
5
5
  /**
6
- * A resource-backed job worker — a thin facade composing a `Queue` (`@orkestrel/queue`)
7
- * with a `Pool` (`@orkestrel/pool`).
6
+ * Represents a resource-backed job worker — a thin facade composing a `Queue`
7
+ * (`@orkestrel/queue`) with a `Pool` (`@orkestrel/pool`).
8
8
  *
9
9
  * @remarks
10
10
  * - **Composition, not reimplementation.** The Worker owns a `Pool` (built from
@@ -19,7 +19,7 @@ import { Queue } from "@orkestrel/queue";
19
19
  * options. At most one resource exists per in-flight job by default, and idle resources are
20
20
  * reused across jobs.
21
21
  * - **Acquire over the attempt signal.** Each job acquires using the attempt's
22
- * `execution.signal`, so an `abort` / `timeout` while waiting for a resource rejects
22
+ * `context.signal`, so an `abort` / `timeout` while waiting for a resource rejects
23
23
  * the acquire — the Queue then handles retry / rejection, and there is no token to
24
24
  * release (the resource was never leased).
25
25
  * - **Lifecycle (§10).** `enqueue` / `restore` / `start` / `stop` / `pause` / `resume` /
@@ -119,10 +119,10 @@ var Worker = class {
119
119
  this.#teardown(ending);
120
120
  return ending.promise;
121
121
  }
122
- async #handle(input, execution) {
123
- const token = await this.#pool.acquire(execution.signal);
122
+ async #handle(input, context) {
123
+ const token = await this.#pool.acquire(context.signal);
124
124
  try {
125
- return await this.#handler(input, token.value, execution);
125
+ return await this.#handler(input, token.value, context);
126
126
  } finally {
127
127
  token.release();
128
128
  }
@@ -158,14 +158,14 @@ var Worker = class {
158
158
  //#endregion
159
159
  //#region src/core/factories.ts
160
160
  /**
161
- * Create a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
161
+ * Creates a resource-backed job worker — a `Queue` (`@orkestrel/queue`) marrying a `Pool`
162
162
  * (`@orkestrel/pool`). Each enqueued input runs through the handler against an
163
163
  * automatically acquired pooled resource (released when the job settles), with the
164
164
  * queue's bounded concurrency, retries, and per-attempt timeout / abort.
165
165
  *
166
166
  * @remarks
167
- * The pool's `max` defaults to `concurrency`, so resources match the jobs in flight and
168
- * are reused across jobs. A handler that throws still releases its resource (the
167
+ * Default for the pool's `max`: the `concurrency` value, so resources match the jobs in flight.
168
+ * Resources are reused across jobs. A handler that throws still releases its resource (the
169
169
  * acquire/release pair brackets the call in a `finally`), so a later job reuses it. The
170
170
  * lifecycle (`start` / `stop` / `pause` / `resume` / `abort` / `clear` / `destroy`)
171
171
  * delegates to the queue; `destroy` also tears the pool down. Observable (§13): a typed
@@ -174,8 +174,8 @@ var Worker = class {
174
174
  * @typeParam TInput - The work input each job carries
175
175
  * @typeParam TResource - The pooled resource each job runs against
176
176
  * @typeParam TResult - The value the handler resolves for a job
177
- * @param options - The `handler` and `pool` plus optional `concurrency` (default `1`),
178
- * `retries` (default `0`), and a default per-attempt `timeout` in milliseconds
177
+ * @param options - The `handler` and `pool` plus the optional `concurrency`, `retries`,
178
+ * `timeout`, `store`, `on`, and `error` keys (see {@link WorkerOptions})
179
179
  * @returns A working {@link WorkerInterface}
180
180
  *
181
181
  * @example