@dokebi/worker
v0.4.1
Published
Worker thread pool for CPU-heavy functions in a Dokebi app.
Maintainers
Readme
@dokebi/worker
An optional plugin that sends CPU work to Node.js worker threads. core ^0.4.0, Node.js 24.0.0 or later, version 0.4.1 (unpublished). Cluster processes and HTTP port sharing belong to other packages. AI agents start with AI.md.
schemaVersion: 1
options:
dokebi-worker:
module: src/infra/worker/tasks.ts
size: 2
maxPending: 128
startupTimeoutMs: 5000
executionTimeoutMs: 0
maxThreadCrashes: 5
threadCrashWindowMs: 60000| Key | Type | Default | Description |
|---|---|---|---|
| module | string | src/infra/worker/tasks.ts | Local path or file URL exporting a default function |
| size | integer 1–64 | 1–4 by CPU count | Threads |
| maxPending | integer 0–100000 | 128 | Waiting tasks, running ones excluded |
| startupTimeoutMs | integer ms | 5000 | Module load deadline |
| executionTimeoutMs | integer ms | 0 (off) | Per-task deadline from dispatch |
| maxThreadCrashes | integer 0–1000 | 5 | Crashes replaced within the window |
| threadCrashWindowMs | integer ms | 60000 | Crash counting window |
module is a local path or file URL that exports a default function; a relative path is resolved from cwd. Remote URLs are not allowed. 0.4.0 renamed maxQueue to maxPending (D-0071); the old name still works with an OPTION_DEPRECATED warning.
createPlugin({ app: app.view, options? }) is a plugin contract v2 (definePlugin) factory. app is required and must be the app.view core created. Without options it uses app.config['dokebi-worker'] ({} when null); given options are used alone. A configuration error is INVALID_PLUGIN_OPTIONS (its cause has the code INVALID_OPTIONS); unknown input such as dependencies is INVALID_PLUGIN_INPUT. After the app starts use app.get(plugin); consumers get the same pool with a descriptor declared in metadata.dependencies and context.getDependency(descriptor), or with context.get(plugin). The plugin owns the shutdown in the lifecycle.
The CLI install manifest is schemaVersion 2 and creates src/infra/worker/tasks.ts from scaffold/tasks.ts through dokebi.install.files. The file is user-owned, and remove keeps it when modified.
Outside an app use WorkerPool.open(options, { signal? }) and close it in finally. That signal covers startup only; aborting it after the pool is ready does not close the pool.
pool.run(input, { signal?, transferList?, executionTimeoutMs? }) returns Promise<unknown>. signal cancels only queued tasks with ABORTED and never stops a running task. Input and output follow Node's structured clone rules.
transferList holds at most 1024 items and only the list is copied at submit. The input and buffer contents belong to the caller until dispatch, so do not change them after submitting. The resources move at dispatch, and cancelling a queued task does not detach buffers. Duplicate or non-transferable items are rejected at dispatch with CLONE_FAILED, and later tasks go on.
The execution deadline starts at dispatch and excludes queue waiting. Only the task past it gets EXECUTION_TIMEOUT, and only its thread is terminated and replaced. Other active and queued tasks continue. A thread crash (error, unexpected exit, messageerror, a message outside the protocol) ends only the task that thread was running with WORKER_FAILED (cause: the original error) and replaces the thread. When crashes exceed maxThreadCrashes within threadCrashWindowMs, the whole pool closes with WORKER_CRASH_LOOP; when a replacement thread cannot start (module load failure, startup deadline passed) it closes with WORKER_REPLACEMENT_FAILED. Timeouts do not count as crashes. Tasks are never rerun. Timers depend on the parent event loop making progress. See D-0050.
maxPending: 0 still dispatches at once to an idle thread. The queue is FIFO; size, queued and active show the state. pool.status is a snapshot of state, closeCode, size, ready, active, queued, replaced, crashes and timeouts. Repeated close calls return the same completion Promise, which waits for thread termination after rejecting every task.
The main errors are INVALID_OPTIONS, STARTUP_TIMEOUT, ABORTED, QUEUE_FULL, CLONE_FAILED, TASK_FAILED, EXECUTION_TIMEOUT, WORKER_FAILED, WORKER_CRASH_LOOP, WORKER_REPLACEMENT_FAILED and POOL_CLOSED, all core DokebiErrors with fix/hint where a fix is known. WORKER_EXIT and INVALID_MESSAGE come as the cause of WORKER_FAILED (directly during open). TASK_FAILED keeps the thrown error as its cause (name, message, stack, a string or number code, the cause chain), so never put sensitive data in task errors.
Install with the CLI: npx dokebi add @dokebi/worker. Example 13 shows transfer, the execution deadline and thread replacement.
