import { Worker } from 'node:worker_threads'; interface WorkerPoolTask { resolve: (result: TResult) => void; reject: (error: Error) => void; } interface WorkerWrapper { worker: Worker; busy: boolean; } /** * Generic worker pool. Subclasses define the task type and how to post messages * to the worker. The pool manages the worker lifecycle, task queue, and * worker replacement on crash. * * Worker responses must follow the shape { success: boolean, result?: TResult, error?: string }. * * The worker script path is passed to the constructor and resolved relative to the * subclass file using the static `resolveWorkerPath` helper. */ declare abstract class WorkerPool, TResult> { protected workers: WorkerWrapper[]; private queue; readonly maxWorkers: number; private readonly workerPath; private isTerminating; private readonly workerData; private activeTasks; private inFlightCount; private slotWaiters; /** * @param workerData Passed verbatim to every Worker this pool creates, * including replacements after a crash. Needed by pools whose workers must * reach shared memory: a SharedArrayBuffer sent this way is shared, not * copied, so the worker addresses the same bytes as the main thread. */ constructor(maxWorkers: number, workerPath: string, workerData?: unknown); /** Options for every Worker this pool creates. Empty unless workerData was given. */ private get workerOptions(); /** * Send a message to every worker in the pool, bypassing the task queue. * * For out-of-band control messages -- profiling, diagnostics -- that must * reach each worker regardless of whether it is busy. Worker threads never * receive process signals, so this is the only way to ask them to act. */ broadcast(message: unknown): number; /** * Resolve the path to a worker script relative to the calling module. * * Pass `import.meta.url` from the subclass file along with the script name * (without extension). The extension is inferred from the calling module's * own extension so that both the TypeScript source (.ts) and the compiled * output (.mjs / .js) are handled correctly. * * @example * constructor(maxWorkers: number) { * super(maxWorkers, WorkerPool.resolveWorkerPath(import.meta.url, "my_worker")); * } */ static resolveWorkerPath(importMetaUrl: string, scriptName: string): string; /** Post the task's payload to the worker. */ protected abstract postTaskMessage(worker: Worker, task: TTask): void; initialize(): void; isInitialized(): boolean; /** * Acquire a back-pressure slot before submitting work to the pool. * Resolves immediately if fewer than `maxWorkers` chunksets are in flight; * otherwise waits until a slot is released. Callers must call `releaseSlot()` * when the submitted task settles (resolve or reject). * * Moving back-pressure into the pool ensures a single global bound on * buffered memory regardless of how many concurrent callers share the pool. */ acquireSlot(): Promise; releaseSlot(): void; protected enqueueTask(task: TTask): void; private processNextQueuedTask; private rejectAllQueuedTasks; private rejectAllActiveTasks; private executeTask; /** * Terminate all workers and reject all pending tasks. * * This pool is NOT designed to be reused after termination. * Create a new instance if a fresh pool is needed. */ terminate(): Promise; } export { WorkerPool, type WorkerPoolTask };