UNPKG

poolifier

Version:

Fast and small Node.js Worker_Threads and Cluster Worker Pool

1,472 lines (1,463 loc) 82.8 kB
import { TransferListItem, MessagePort, MessageChannel, WorkerOptions as WorkerOptions$1, Worker as Worker$1 } from 'node:worker_threads'; import { EventEmitter, EventEmitterAsyncResource } from 'node:events'; import { AsyncResource } from 'node:async_hooks'; import { EventLoopUtilization } from 'node:perf_hooks'; import { ClusterSettings, Worker } from 'node:cluster'; /** * Circular buffer designed for positive numbers. * @internal */ declare class CircularBuffer { private readonly items; private readonly maxArrayIdx; private readIdx; private writeIdx; size: number; /** * @param size - Buffer size. @defaultValue defaultBufferSize * @returns CircularBuffer. */ constructor(size?: number); /** * Checks the buffer size. * @param size - Buffer size. */ private checkSize; /** * Checks whether the buffer is empty. * @returns Whether the buffer is empty. */ empty(): boolean; /** * Checks whether the buffer is full. * @returns Whether the buffer is full. */ full(): boolean; /** * Gets number from buffer. * @returns Number from buffer. */ get(): number | undefined; /** * Puts number into buffer. * @param number - Number to put into buffer. */ put(number: number): void; /** * Returns buffer as numbers' array. * @returns Numbers' array. */ toArray(): number[]; } /** * Enumeration of worker choice strategies. */ declare const WorkerChoiceStrategies: Readonly<{ FAIR_SHARE: 'FAIR_SHARE'; INTERLEAVED_WEIGHTED_ROUND_ROBIN: 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'; LEAST_BUSY: 'LEAST_BUSY'; LEAST_ELU: 'LEAST_ELU'; LEAST_USED: 'LEAST_USED'; ROUND_ROBIN: 'ROUND_ROBIN'; WEIGHTED_ROUND_ROBIN: 'WEIGHTED_ROUND_ROBIN'; }>; /** * Worker choice strategy. */ type WorkerChoiceStrategy = keyof typeof WorkerChoiceStrategies; /** * Enumeration of measurements. */ declare const Measurements: Readonly<{ elu: 'elu'; runTime: 'runTime'; waitTime: 'waitTime'; }>; /** * Measurement. */ type Measurement = keyof typeof Measurements; /** * Measurement options. */ interface MeasurementOptions { /** * Set measurement median. */ readonly median: boolean; } /** * Worker choice strategy options. */ interface WorkerChoiceStrategyOptions { /** * Event loop utilization options. * @defaultValue \{ median: false \} */ readonly elu?: MeasurementOptions; /** * Measurement to use in worker choice strategy supporting it. */ readonly measurement?: Measurement; /** * Runtime options. * @defaultValue \{ median: false \} */ readonly runTime?: MeasurementOptions; /** * Wait time options. * @defaultValue \{ median: false \} */ readonly waitTime?: MeasurementOptions; /** * Worker weights to use for weighted round robin worker selection strategies. * A weight is tasks maximum execution time in milliseconds for a worker node. * @defaultValue Weights computed automatically given the CPU performance. */ weights?: Record<number, number>; } /** * Measurement statistics requirements. * @internal */ interface MeasurementStatisticsRequirements { /** * Requires measurement aggregate. */ aggregate: boolean; /** * Requires measurement average. */ average: boolean; /** * Requires measurement median. */ median: boolean; } /** * Pool worker node worker usage statistics requirements. * @internal */ interface TaskStatisticsRequirements { /** * Tasks event loop utilization requirements. */ readonly elu: MeasurementStatisticsRequirements; /** * Tasks runtime requirements. */ readonly runTime: MeasurementStatisticsRequirements; /** * Tasks wait time requirements. */ readonly waitTime: MeasurementStatisticsRequirements; } /** * Strategy policy. * @internal */ interface StrategyPolicy { /** * Expects the newly created dynamic worker to be flagged as ready. */ readonly dynamicWorkerReady: boolean; /** * Expects tasks execution on the newly created dynamic worker. */ readonly dynamicWorkerUsage: boolean; } /** * Worker choice strategy interface. * @internal */ interface IWorkerChoiceStrategy { /** * Chooses a worker node in the pool and returns its key. * If no worker nodes are not eligible, `undefined` is returned. * If `undefined` is returned, the caller retry. * @returns The worker node key or `undefined`. */ readonly choose: () => number | undefined; /** * Removes the worker node key from strategy internals. * @param workerNodeKey - The worker node key. * @returns `true` if the worker node key is removed, `false` otherwise. */ readonly remove: (workerNodeKey: number) => boolean; /** * Resets strategy internals. * @returns `true` if the reset is successful, `false` otherwise. */ readonly reset: () => boolean; /** * Sets the worker choice strategy options. * @param opts - The worker choice strategy options. */ readonly setOptions: (opts: undefined | WorkerChoiceStrategyOptions) => void; /** * Strategy policy. */ readonly strategyPolicy: StrategyPolicy; /** * Tasks statistics requirements. */ readonly taskStatisticsRequirements: TaskStatisticsRequirements; /** * Updates the worker node key strategy internals. * This is called after a task has been executed on a worker node. * @returns `true` if the update is successful, `false` otherwise. */ readonly update: (workerNodeKey: number) => boolean; } /** * Enumeration of kill behaviors. */ declare const KillBehaviors: Readonly<{ HARD: 'HARD'; SOFT: 'SOFT'; }>; /** * Kill behavior. */ type KillBehavior = keyof typeof KillBehaviors; /** * Handler called when a worker is killed. */ type KillHandler = () => Promise<void> | void; /** * Options for workers. */ interface WorkerOptions { /** * `killBehavior` dictates if your worker will be deleted in case a task is active on it. * * - SOFT: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker **won't** be deleted. * - HARD: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but the worker is stealing tasks or a task is executing or queued, then the worker will be deleted. * * This option only apply to the newly created workers. * @defaultValue KillBehaviors.SOFT */ killBehavior?: KillBehavior; /** * The function to call when a worker is killed. * @defaultValue `() => {}` */ killHandler?: KillHandler; /** * Maximum waiting time in milliseconds for tasks on newly created workers. It must be greater or equal than 5. * * After this time, newly created workers will be terminated. * The last active time of your worker will be updated when it terminates a task. * * - If `killBehavior` is set to `KillBehaviors.HARD` this value represents also the timeout for the tasks that you submit to the pool, * when this timeout expires your tasks is interrupted before completion and removed. The worker is killed if is not part of the minimum size of the pool. * - If `killBehavior` is set to `KillBehaviors.SOFT` your tasks have no timeout and your workers will not be terminated until your task is completed. * @defaultValue 60000 */ maxInactiveTime?: number; } /** * Worker error. * @typeParam Data - Type of data sent to the worker triggering an error. This can only be structured-cloneable data. */ interface WorkerError<Data = unknown> { /** * Data triggering the error. */ readonly data?: Data; /** * Error object. */ readonly error?: Error; /** * Error message. */ readonly message: string; /** * Task function name triggering the error. */ readonly name?: string; /** * Error stack trace. */ readonly stack?: string; } /** * Task performance. * @internal */ interface TaskPerformance { /** * Task event loop utilization. */ readonly elu?: EventLoopUtilization; /** * Task name. */ readonly name: string; /** * Task runtime. */ readonly runTime?: number; /** * Task performance timestamp. */ readonly timestamp: number; } /** * Worker task performance statistics computation settings. * @internal */ interface WorkerStatistics { /** * Whether the worker computes the task event loop utilization (ELU) or not. */ readonly elu: boolean; /** * Whether the worker computes the task runtime or not. */ readonly runTime: boolean; } /** * Task function properties. */ interface TaskFunctionProperties { /** * Task function name. */ readonly name: string; /** * Task function priority. Lower values have higher priority. */ readonly priority?: number; /** * Task function worker choice strategy. */ readonly strategy?: WorkerChoiceStrategy; } /** * Message object that is passed as a task between main worker and worker. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @internal */ interface Task<Data = unknown> { /** * Task input data that will be passed to the worker. */ readonly data?: Data; /** * Task name. */ readonly name?: string; /** * Task priority. Lower values have higher priority. * @defaultValue 0 */ readonly priority?: number; /** * Task worker choice strategy. */ readonly strategy?: WorkerChoiceStrategy; /** * Task UUID. */ readonly taskId?: `${string}-${string}-${string}-${string}-${string}`; /** * Timestamp. */ readonly timestamp?: number; /** * Array of transferable objects. */ readonly transferList?: readonly TransferListItem[]; } /** * Message object that is passed between main worker and worker. * @typeParam Data - Type of data sent to the worker or execution response. This can only be structured-cloneable data. * @typeParam ErrorData - Type of data sent to the worker triggering an error. This can only be structured-cloneable data. * @internal */ interface MessageValue<Data = unknown, ErrorData = unknown> extends Task<Data> { /** * Whether the worker starts or stops its activity check. */ readonly checkActive?: boolean; /** * Kill code. */ readonly kill?: 'failure' | 'success' | KillBehavior | true; /** * Message port. */ readonly port?: MessagePort; /** * Whether the worker is ready or not. */ readonly ready?: boolean; /** * Whether the worker computes the given statistics or not. */ readonly statistics?: WorkerStatistics; /** * Task function serialized to string. */ readonly taskFunction?: string; /** * Task function operation: * - `'add'` - Add a task function. * - `'remove'` - Remove a task function. * - `'default'` - Set a task function as default. */ readonly taskFunctionOperation?: 'add' | 'default' | 'remove'; /** * Whether the task function operation is successful or not. */ readonly taskFunctionOperationStatus?: boolean; /** * Task function properties. */ readonly taskFunctionProperties?: TaskFunctionProperties; /** * Task functions properties. */ readonly taskFunctionsProperties?: TaskFunctionProperties[]; /** * Task performance. */ readonly taskPerformance?: TaskPerformance; /** * Worker error. */ readonly workerError?: WorkerError<ErrorData>; /** * Worker id. */ readonly workerId?: number; } /** * An object holding the task execution response promise resolve/reject callbacks. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @internal */ interface PromiseResponseWrapper<Response = unknown> { /** * The asynchronous resource used to track the task execution. */ readonly asyncResource?: AsyncResource; /** * Reject callback to reject the promise. */ readonly reject: (reason?: unknown) => void; /** * Resolve callback to fulfill the promise. */ readonly resolve: (value: PromiseLike<Response> | Response) => void; /** * The worker node key executing the task. */ readonly workerNodeKey: number; } /** * Remove readonly modifier from all properties of T. * @typeParam T - Type to remove readonly modifier. * @internal */ type Writable<T> = { -readonly [P in keyof T]: T[P]; }; /** * Task synchronous function that can be executed. * @param data - Data sent to the worker. * @returns Execution response. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ type TaskSyncFunction<Data = unknown, Response = unknown> = (data?: Data) => Response; /** * Task asynchronous function that can be executed. * This function must return a promise. * @param data - Data sent to the worker. * @returns Execution response promise. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ type TaskAsyncFunction<Data = unknown, Response = unknown> = (data?: Data) => Promise<Response>; /** * Task function that can be executed. * This function can be synchronous or asynchronous. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ type TaskFunction<Data = unknown, Response = unknown> = TaskAsyncFunction<Data, Response> | TaskSyncFunction<Data, Response>; /** * Task function object. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ interface TaskFunctionObject<Data = unknown, Response = unknown> { /** * Task function priority. Lower values have higher priority. */ priority?: number; /** * Task function worker choice strategy. */ strategy?: WorkerChoiceStrategy; /** * Task function. */ taskFunction: TaskFunction<Data, Response>; } /** * Tasks functions that can be executed. * The key is the name of the task function or task function object. * The value is the task function or task function object. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ type TaskFunctions<Data = unknown, Response = unknown> = Record<string, TaskFunction<Data, Response> | TaskFunctionObject<Data, Response>>; /** * Task function operation result. */ interface TaskFunctionOperationResult { error?: Error; status: boolean; } /** * Callback invoked when the worker has started successfully. * @typeParam Worker - Type of worker. */ type OnlineHandler<Worker extends IWorker> = (this: Worker) => void; /** * Callback invoked if the worker has received a message. * @typeParam Worker - Type of worker. */ type MessageHandler<Worker extends IWorker> = (this: Worker, message: unknown) => void; /** * Callback invoked if the worker raised an error. * @typeParam Worker - Type of worker. */ type ErrorHandler<Worker extends IWorker> = (this: Worker, error: Error) => void; /** * Callback invoked when the worker exits successfully. * @typeParam Worker - Type of worker. */ type ExitHandler<Worker extends IWorker> = (this: Worker, exitCode: number) => void; /** * Worker event handler. * @typeParam Worker - Type of worker. */ type EventHandler<Worker extends IWorker> = ErrorHandler<Worker> | ExitHandler<Worker> | MessageHandler<Worker> | OnlineHandler<Worker>; /** * Measurement statistics. * @internal */ interface MeasurementStatistics { /** * Measurement aggregate. */ aggregate?: number; /** * Measurement average. */ average?: number; /** * Measurement history. */ readonly history: CircularBuffer; /** * Measurement maximum. */ maximum?: number; /** * Measurement median. */ median?: number; /** * Measurement minimum. */ minimum?: number; } /** * Event loop utilization measurement statistics. * @internal */ interface EventLoopUtilizationMeasurementStatistics { readonly active: MeasurementStatistics; readonly idle: MeasurementStatistics; utilization?: number; } /** * Task statistics. * @internal */ interface TaskStatistics { /** * Number of executed tasks. */ executed: number; /** * Number of executing tasks. */ executing: number; /** * Number of failed tasks. */ failed: number; /** * Maximum number of queued tasks. */ readonly maxQueued?: number; /** * Number of queued tasks. */ readonly queued: number; /** * Number of sequentially stolen tasks. */ sequentiallyStolen: number; /** * Number of stolen tasks. */ stolen: number; } /** * Enumeration of worker types. */ declare const WorkerTypes: Readonly<{ cluster: 'cluster'; thread: 'thread'; }>; /** * Worker type. */ type WorkerType = keyof typeof WorkerTypes; /** * Worker information. * @internal */ interface WorkerInfo { /** * Back pressure flag. * This flag is set to `true` when worker node tasks queue is back pressured. */ backPressure: boolean; /** * Back pressure stealing flag. * This flag is set to `true` when worker node is stealing one task from another back pressured worker node. */ backPressureStealing: boolean; /** * Continuous stealing flag. * This flag is set to `true` when worker node is continuously stealing tasks from other worker nodes. */ continuousStealing: boolean; /** * Dynamic flag. */ dynamic: boolean; /** * Worker id. */ readonly id: number | undefined; /** * Ready flag. */ ready: boolean; /** * Stealing flag. * This flag is set to `true` when worker node is stealing one task from another worker node. */ stealing: boolean; /** * Stolen flag. * This flag is set to `true` when worker node has one task stolen from another worker node. */ stolen: boolean; /** * Task functions properties. */ taskFunctionsProperties?: TaskFunctionProperties[]; /** * Worker type. */ readonly type: WorkerType; } /** * Worker usage statistics. * @internal */ interface WorkerUsage { /** * Tasks event loop utilization statistics. */ readonly elu: EventLoopUtilizationMeasurementStatistics; /** * Tasks runtime statistics. */ readonly runTime: MeasurementStatistics; /** * Tasks statistics. */ readonly tasks: TaskStatistics; /** * Tasks wait time statistics. */ readonly waitTime: MeasurementStatistics; } /** * Worker choice strategy data. * @internal */ interface StrategyData { virtualTaskEndTimestamp?: number; } /** * Worker interface. */ interface IWorker extends EventEmitter { /** * Cluster worker disconnect. */ readonly disconnect?: () => void; /** * Cluster worker id. */ readonly id?: number; /** * Cluster worker kill. */ readonly kill?: (signal?: string) => void; /** * Registers an event handler. * @param event - The event. * @param handler - The event handler. */ readonly on: (event: string, handler: EventHandler<this>) => this; /** * Registers once an event handler. * @param event - The event. * @param handler - The event handler. */ readonly once: (event: string, handler: EventHandler<this>) => this; /** * Stop all JavaScript execution in the worker thread as soon as possible. * Returns a Promise for the exit code that is fulfilled when the `'exit' event` is emitted. */ readonly terminate?: () => Promise<number>; /** * Worker thread worker id. */ readonly threadId?: number; /** * Calling `unref()` on a worker allows the thread to exit if this is the only * active handle in the event system. If the worker is already `unref()`ed calling`unref()` again has no effect. * @since v10.5.0 */ readonly unref?: () => void; } /** * Worker node options. * @internal */ interface WorkerNodeOptions { env?: Record<string, unknown>; tasksQueueBackPressureSize: number | undefined; tasksQueueBucketSize: number | undefined; tasksQueuePriority: boolean | undefined; workerOptions?: WorkerOptions$1; } /** * Worker node interface. * @typeParam Worker - Type of worker. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @internal */ interface IWorkerNode<Worker extends IWorker, Data = unknown> extends EventEmitter { /** * Clears tasks queue. */ readonly clearTasksQueue: () => void; /** * Deletes task function worker usage statistics. * @param name - The task function name. * @returns `true` if the task function worker usage statistics were deleted, `false` otherwise. */ readonly deleteTaskFunctionWorkerUsage: (name: string) => boolean; /** * Dequeue last prioritized task. * @returns The dequeued task. */ readonly dequeueLastPrioritizedTask: () => Task<Data> | undefined; /** * Dequeue task. * @param bucket - The prioritized bucket to dequeue from. @defaultValue 0 * @returns The dequeued task. */ readonly dequeueTask: (bucket?: number) => Task<Data> | undefined; /** * Enqueue task. * @param task - The task to queue. * @returns The tasks queue size. */ readonly enqueueTask: (task: Task<Data>) => number; /** * Gets task function worker usage statistics. * @param name - The task function name. * @returns The task function worker usage statistics if the task function worker usage statistics are initialized, `undefined` otherwise. */ readonly getTaskFunctionWorkerUsage: (name: string) => undefined | WorkerUsage; /** * Worker info. */ readonly info: WorkerInfo; /** * Message channel (worker thread only). */ readonly messageChannel?: MessageChannel; /** * Registers once a worker event handler. * @param event - The event. * @param handler - The event handler. */ readonly registerOnceWorkerEventHandler: (event: string, handler: EventHandler<Worker>) => void; /** * Registers a worker event handler. * @param event - The event. * @param handler - The event handler. */ readonly registerWorkerEventHandler: (event: string, handler: EventHandler<Worker>) => void; /** * Sets tasks queue priority. * @param enablePriority - Whether to enable tasks queue priority. */ readonly setTasksQueuePriority: (enablePriority: boolean) => void; /** * Worker choice strategy data. * This is used to store data that are specific to the worker choice strategy. */ strategyData?: StrategyData; /** * Tasks queue back pressure size. * This is the number of tasks that can be enqueued before the worker node has back pressure. */ tasksQueueBackPressureSize: number; /** * Tasks queue size. * @returns The tasks queue size. */ readonly tasksQueueSize: () => number; /** * Terminates the worker node. */ readonly terminate: () => Promise<void>; /** * Worker usage statistics. */ readonly usage: WorkerUsage; /** * Worker. */ readonly worker: Worker; } /** * Worker node event detail. * @internal */ interface WorkerNodeEventDetail { workerId?: number; workerNodeKey?: number; } /** * Enumeration of pool types. */ declare const PoolTypes: Readonly<{ dynamic: 'dynamic'; fixed: 'fixed'; }>; /** * Pool type. */ type PoolType = keyof typeof PoolTypes; /** * Enumeration of pool events. */ declare const PoolEvents: Readonly<{ backPressure: 'backPressure'; backPressureEnd: 'backPressureEnd'; busy: 'busy'; busyEnd: 'busyEnd'; destroy: 'destroy'; empty: 'empty'; error: 'error'; full: 'full'; fullEnd: 'fullEnd'; ready: 'ready'; taskError: 'taskError'; }>; /** * Pool event. */ type PoolEvent = keyof typeof PoolEvents; /** * Pool information. */ interface PoolInfo { readonly backPressure?: boolean; /** Pool tasks back pressure worker nodes. */ readonly backPressureWorkerNodes?: number; /** Pool busy worker nodes. */ readonly busyWorkerNodes: number; readonly defaultStrategy: WorkerChoiceStrategy; /** Pool dynamic worker nodes. */ readonly dynamicWorkerNodes?: number; readonly elu?: { active: { readonly average?: number; readonly maximum: number; readonly median?: number; readonly minimum: number; }; idle: { readonly average?: number; readonly maximum: number; readonly median?: number; readonly minimum: number; }; utilization: { readonly average?: number; readonly median?: number; }; }; readonly executedTasks: number; readonly executingTasks: number; readonly failedTasks: number; /** Pool idle worker nodes. */ readonly idleWorkerNodes: number; readonly maxQueuedTasks?: number; readonly maxSize: number; readonly minSize: number; readonly queuedTasks?: number; readonly ready: boolean; readonly runTime?: { readonly average?: number; readonly maximum: number; readonly median?: number; readonly minimum: number; }; readonly started: boolean; /** Pool tasks stealing worker nodes. */ readonly stealingWorkerNodes?: number; readonly stolenTasks?: number; readonly strategyRetries: number; readonly type: PoolType; /** Pool utilization. */ readonly utilization?: number; readonly version: string; readonly waitTime?: { readonly average?: number; readonly maximum: number; readonly median?: number; readonly minimum: number; }; readonly worker: WorkerType; /** Pool total worker nodes. */ readonly workerNodes: number; } /** * Worker node tasks queue options. */ interface TasksQueueOptions { /** * Maximum number of tasks that can be executed concurrently on a worker node. * @defaultValue 1 */ readonly concurrency?: number; /** * Maximum tasks queue size per worker node flagging it as back pressured. * @defaultValue (pool maximum size)^2 */ readonly size?: number; /** * Queued tasks finished timeout in milliseconds at worker node termination. * @defaultValue 2000 */ readonly tasksFinishedTimeout?: number; /** * Whether to enable tasks stealing under back pressure. * @defaultValue true */ readonly tasksStealingOnBackPressure?: boolean; /** * Ratio of worker nodes that can steal tasks from another worker node. * @defaultValue 0.6 */ readonly tasksStealingRatio?: number; /** * Whether to enable task stealing on idle. * @defaultValue true */ readonly taskStealing?: boolean; } /** * Options for a poolifier pool. * @typeParam Worker - Type of worker. */ interface PoolOptions<Worker extends IWorker> { /** * Pool events integrated with async resource emission. * @defaultValue true */ enableEvents?: boolean; /** * Pool worker node tasks queue. * @defaultValue false */ enableTasksQueue?: boolean; /** * Key/value pairs to add to worker process environment. * @see https://nodejs.org/api/cluster.html#cluster_cluster_fork_env */ env?: Record<string, unknown>; /** * A function that will listen for error event on each worker. * @defaultValue `() => {}` */ errorHandler?: ErrorHandler<Worker>; /** * A function that will listen for exit event on each worker. * @defaultValue `() => {}` */ exitHandler?: ExitHandler<Worker>; /** * A function that will listen for message event on each worker. * @defaultValue `() => {}` */ messageHandler?: MessageHandler<Worker>; /** * A function that will listen for online event on each worker. * @defaultValue `() => {}` */ onlineHandler?: OnlineHandler<Worker>; /** * Restart worker on error. */ restartWorkerOnError?: boolean; /** * Cluster settings. * @see https://nodejs.org/api/cluster.html#cluster_cluster_settings */ settings?: ClusterSettings; /** * Whether to start the minimum number of workers at pool initialization. * @defaultValue true */ startWorkers?: boolean; /** * Pool worker node tasks queue options. */ tasksQueueOptions?: TasksQueueOptions; /** * The default worker choice strategy to use in this pool. * @defaultValue WorkerChoiceStrategies.ROUND_ROBIN */ workerChoiceStrategy?: WorkerChoiceStrategy; /** * The worker choice strategy options. */ workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions; /** * Worker options. * @see https://nodejs.org/api/worker_threads.html#new-workerfilename-options */ workerOptions?: WorkerOptions$1; } /** * Contract definition for a poolifier pool. * @typeParam Worker - Type of worker which manages this pool. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ interface IPool<Worker extends IWorker, Data = unknown, Response = unknown> { /** * Adds a task function to this pool. * If a task function with the same name already exists, it will be overwritten. * @param name - The name of the task function. * @param fn - The task function. * @returns `true` if the task function was added, `false` otherwise. * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string or an empty string. * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `fn` parameter is not a function or task function object. */ readonly addTaskFunction: (name: string, fn: TaskFunction<Data, Response> | TaskFunctionObject<Data, Response>) => Promise<boolean>; /** * Terminates all workers in this pool. */ readonly destroy: () => Promise<void>; /** * Pool event emitter integrated with async resource. * The async tracking tooling identifier is `poolifier:<PoolType>-<WorkerType>-pool`. * * Events that can currently be listened to: * * - `'ready'`: Emitted when the number of workers created in the pool has reached the minimum size expected and are ready. If the pool is dynamic with a minimum number of workers set to zero, this event is emitted when the pool is started. * - `'busy'`: Emitted when the number of workers created in the pool has reached the maximum size expected and are executing concurrently their tasks quota. * - `'busyEnd'`: Emitted when the number of workers created in the pool has reached the maximum size expected and are no longer executing concurrently their tasks quota. * - `'full'`: Emitted when the pool is dynamic and the number of workers created has reached the maximum size expected. * - `'fullEnd'`: Emitted when the pool is dynamic and the number of workers created has no longer reached the maximum size expected. * - `'empty'`: Emitted when the pool is dynamic with a minimum number of workers set to zero and the number of workers has reached the minimum size expected. * - `'destroy'`: Emitted when the pool is destroyed. * - `'error'`: Emitted when an uncaught error occurs. * - `'taskError'`: Emitted when an error occurs while executing a task. * - `'backPressure'`: Emitted when the number of workers created in the pool has reached the maximum size expected and are back pressured (i.e. their tasks queue is full: queue size \>= maximum queue size). * - `'backPressureEnd'`: Emitted when the number of workers created in the pool has reached the maximum size expected and are no longer back pressured (i.e. their tasks queue is no longer full: queue size \< maximum queue size). */ readonly emitter?: EventEmitterAsyncResource; /** * Enables/disables the worker node tasks queue in this pool. * @param enable - Whether to enable or disable the worker node tasks queue. * @param tasksQueueOptions - The worker node tasks queue options. */ readonly enableTasksQueue: (enable: boolean, tasksQueueOptions?: TasksQueueOptions) => void; /** * Executes the specified function in the worker constructor with the task data input parameter. * @param data - The optional task input data for the specified task function. This can only be structured-cloneable data. * @param name - The optional name of the task function to execute. If not specified, the default task function will be executed. * @param transferList - An optional array of transferable objects to transfer ownership of. Ownership of the transferred objects is given to the chosen pool's worker_threads worker and they should not be used in the main thread afterwards. * @returns Promise with a task function response that will be fulfilled when the task is completed. */ readonly execute: (data?: Data, name?: string, transferList?: readonly TransferListItem[]) => Promise<Response>; /** * Whether the specified task function exists in this pool. * @param name - The name of the task function. * @returns `true` if the task function exists, `false` otherwise. */ readonly hasTaskFunction: (name: string) => boolean; /** * Pool information. */ readonly info: PoolInfo; /** * Lists the properties of task functions available in this pool. * @returns The properties of task functions available in this pool. */ readonly listTaskFunctionsProperties: () => TaskFunctionProperties[]; /** * Executes the specified function in the worker constructor with the tasks data iterable input parameter. * @param data - The tasks iterable input data for the specified task function. This can only be an iterable of structured-cloneable data. * @param name - The optional name of the task function to execute. If not specified, the default task function will be executed. * @param transferList - An optional array of transferable objects to transfer ownership of. Ownership of the transferred objects is given to the chosen pool's worker_threads worker and they should not be used in the main thread afterwards. * @returns Promise with an array of task function responses that will be fulfilled when the tasks are completed. */ readonly mapExecute: (data: Iterable<Data>, name?: string, transferList?: readonly TransferListItem[]) => Promise<Response[]>; /** * Removes a task function from this pool. * @param name - The name of the task function. * @returns `true` if the task function was removed, `false` otherwise. */ readonly removeTaskFunction: (name: string) => Promise<boolean>; /** * Sets the default task function in this pool. * @param name - The name of the task function. * @returns `true` if the default task function was set, `false` otherwise. */ readonly setDefaultTaskFunction: (name: string) => Promise<boolean>; /** * Sets the worker node tasks queue options in this pool. * @param tasksQueueOptions - The worker node tasks queue options. */ readonly setTasksQueueOptions: (tasksQueueOptions: TasksQueueOptions) => void; /** * Sets the default worker choice strategy in this pool. * @param workerChoiceStrategy - The default worker choice strategy. * @param workerChoiceStrategyOptions - The worker choice strategy options. */ readonly setWorkerChoiceStrategy: (workerChoiceStrategy: WorkerChoiceStrategy, workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions) => void; /** * Sets the worker choice strategy options in this pool. * @param workerChoiceStrategyOptions - The worker choice strategy options. * @returns `true` if the worker choice strategy options were set, `false` otherwise. */ readonly setWorkerChoiceStrategyOptions: (workerChoiceStrategyOptions: WorkerChoiceStrategyOptions) => boolean; /** * Starts the minimum number of workers in this pool. */ readonly start: () => void; /** * Pool worker nodes. * @internal */ readonly workerNodes: IWorkerNode<Worker, Data>[]; } /** * The worker choice strategies context. * @typeParam Worker - Type of worker. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. * @internal */ declare class WorkerChoiceStrategiesContext<Worker extends IWorker, Data = unknown, Response = unknown> { private readonly pool; /** * The default worker choice strategy in the context. */ private defaultWorkerChoiceStrategy; /** * The maximum number of worker choice strategies execution retries. */ private readonly retries; /** * The worker choice strategies registered in the context. */ private readonly workerChoiceStrategies; /** * The active worker choice strategies in the context policy. */ private workerChoiceStrategiesPolicy; /** * The active worker choice strategies in the context task statistics requirements. */ private workerChoiceStrategiesTaskStatisticsRequirements; /** * The number of worker choice strategies execution retries. */ retriesCount: number; /** * Worker choice strategies context constructor. * @param pool - The pool instance. * @param workerChoiceStrategies - The worker choice strategies. @defaultValue [WorkerChoiceStrategies.ROUND_ROBIN] * @param opts - The worker choice strategy options. */ constructor(pool: IPool<Worker, Data, Response>, workerChoiceStrategies?: WorkerChoiceStrategy[], opts?: WorkerChoiceStrategyOptions); /** * Adds a worker choice strategy to the context. * @param workerChoiceStrategy - The worker choice strategy to add. * @param pool - The pool instance. * @param opts - The worker choice strategy options. * @returns The worker choice strategies. */ private addWorkerChoiceStrategy; /** * Executes the given worker choice strategy. * @param workerChoiceStrategy - The worker choice strategy. * @returns The key of the worker node. * @throws {@link https://nodejs.org/api/errors.html#class-error} If after computed retries the worker node key is null or undefined. */ private executeStrategy; /** * Removes a worker choice strategy from the context. * @param workerChoiceStrategy - The worker choice strategy to remove. * @returns `true` if the worker choice strategy is removed, `false` otherwise. */ private removeWorkerChoiceStrategy; /** * Executes the given worker choice strategy in the context algorithm. * @param workerChoiceStrategy - The worker choice strategy algorithm to execute. @defaultValue this.defaultWorkerChoiceStrategy * @returns The key of the worker node. * @throws {@link https://nodejs.org/api/errors.html#class-error} If after computed retries the worker node key is null or undefined. */ execute(workerChoiceStrategy?: WorkerChoiceStrategy): number; /** * Gets the active worker choice strategies in the context policy. * @returns The strategies policy. */ getPolicy(): StrategyPolicy; /** * Gets the active worker choice strategies in the context task statistics requirements. * @returns The strategies task statistics requirements. */ getTaskStatisticsRequirements(): TaskStatisticsRequirements; /** * Removes the worker node key from the active worker choice strategies in the context. * @param workerNodeKey - The worker node key. * @returns `true` if the removal is successful, `false` otherwise. */ remove(workerNodeKey: number): boolean; /** * Sets the default worker choice strategy to use in the context. * @param workerChoiceStrategy - The default worker choice strategy to set. * @param opts - The worker choice strategy options. */ setDefaultWorkerChoiceStrategy(workerChoiceStrategy: WorkerChoiceStrategy, opts?: WorkerChoiceStrategyOptions): void; /** * Sets the active worker choice strategies in the context options. * @param opts - The worker choice strategy options. */ setOptions(opts: undefined | WorkerChoiceStrategyOptions): void; /** * Synchronizes the active worker choice strategies in the context with the given worker choice strategies. * @param workerChoiceStrategies - The worker choice strategies to synchronize. * @param opts - The worker choice strategy options. */ syncWorkerChoiceStrategies(workerChoiceStrategies: Set<WorkerChoiceStrategy>, opts?: WorkerChoiceStrategyOptions): void; /** * Updates the worker node key in the active worker choice strategies in the context internals. * @param workerNodeKey - The worker node key. * @returns `true` if the update is successful, `false` otherwise. */ update(workerNodeKey: number): boolean; } /** * Base class that implements some shared logic for all poolifier pools. * @typeParam Worker - Type of worker which manages this pool. * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. * @typeParam Response - Type of execution response. This can only be structured-cloneable data. */ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Response = unknown> implements IPool<Worker, Data, Response> { protected readonly minimumNumberOfWorkers: number; protected readonly filePath: string; protected readonly opts: PoolOptions<Worker>; protected readonly maximumNumberOfWorkers?: number | undefined; /** * The task execution response promise map: * - `key`: The message id of each submitted task. * - `value`: An object that contains task's worker node key, execution response promise resolve and reject callbacks, async resource. * * When we receive a message from the worker, we get a map entry with the promise resolve/reject bound to the message id. */ protected promiseResponseMap: Map<`${string}-${string}-${string}-${string}-${string}`, PromiseResponseWrapper<Response>>; /** * Worker choice strategies context referencing worker choice algorithms implementation. */ protected workerChoiceStrategiesContext?: WorkerChoiceStrategiesContext<Worker, Data, Response>; /** * This method is the message listener registered on each worker. * @param message - The message received from the worker. */ protected readonly workerMessageListener: (message: MessageValue<Response>) => void; /** * Whether the pool back pressure event has been emitted or not. */ private backPressureEventEmitted; /** * Whether the pool busy event has been emitted or not. */ private busyEventEmitted; /** * Whether the pool is destroying or not. */ private destroying; /** * Gets task function worker choice strategy, if any. * @param name - The task function name. * @returns The task function worker choice strategy if the task function worker choice strategy is defined, `undefined` otherwise. */ private readonly getTaskFunctionWorkerChoiceStrategy; /** * Gets the worker choice strategies registered in this pool. * @returns The worker choice strategies. */ private readonly getWorkerChoiceStrategies; /** * Gets worker node task function priority, if any. * @param workerNodeKey - The worker node key. * @param name - The task function name. * @returns The worker node task function priority if the worker node task function priority is defined, `undefined` otherwise. */ private readonly getWorkerNodeTaskFunctionPriority; /** * Gets worker node task function worker choice strategy, if any. * @param workerNodeKey - The worker node key. * @param name - The task function name. * @returns The worker node task function worker choice strategy if the worker node task function worker choice strategy is defined, `undefined` otherwise. */ private readonly getWorkerNodeTaskFunctionWorkerChoiceStrategy; private readonly handleWorkerNodeBackPressureEvent; private readonly handleWorkerNodeIdleEvent; private readonly isStealingRatioReached; /** * Whether the pool ready event has been emitted or not. */ private readyEventEmitted; /** * Whether the pool is started or not. */ private started; /** * Whether the pool is starting or not. */ private starting; /** * Whether the minimum number of workers is starting or not. */ private startingMinimumNumberOfWorkers; /** * The start timestamp of the pool. */ private startTimestamp?; private readonly stealTask; /** * The task functions added at runtime map: * - `key`: The task function name. * - `value`: The task function object. */ private readonly taskFunctions; private readonly workerNodeStealTask; /** @inheritDoc */ emitter?: EventEmitterAsyncResource; /** @inheritDoc */ readonly workerNodes: IWorkerNode<Worker, Data>[]; /** * Constructs a new poolifier pool. * @param minimumNumberOfWorkers - Minimum number of workers that this pool manages. * @param filePath - Path to the worker file. * @param opts - Options for the pool. * @param maximumNumberOfWorkers - Maximum number of workers that this pool manages. */ constructor(minimumNumberOfWorkers: number, filePath: string, opts: PoolOptions<Worker>, maximumNumberOfWorkers?: number | undefined); /** * Hook executed after the worker task execution. * Can be overridden. * @param workerNodeKey - The worker node key. * @param message - The received message. */ protected afterTaskExecutionHook(workerNodeKey: number, message: MessageValue<Response>): void; /** * Method hooked up after a worker node has been newly created. * Can be overridden. * @param workerNodeKey - The newly created worker node key. */ protected afterWorkerNodeSetup(workerNodeKey: number): void; /** * Hook executed before the worker task execution. * Can be overridden. * @param workerNodeKey - The worker node key. * @param task - The task to execute. */ protected beforeTaskExecutionHook(workerNodeKey: number, task: Task<Data>): void; /** * Emits dynamic worker creation events. */ protected abstract checkAndEmitDynamicWorkerCreationEvents(): void; /** * Emits dynamic worker destruction events. */ protected abstract checkAndEmitDynamicWorkerDestructionEvents(): void; /** * Creates a new, completely set up dynamic worker node. * @returns New, completely set up dynamic worker node key. */ protected createAndSetupDynamicWorkerNode(): number; /** * Creates a new, completely set up worker node. * @returns New, completely set up worker node key. */ protected createAndSetupWorkerNode(): number; /** * Deregisters a listener callback on the worker given its worker node key. * @param workerNodeKey - The worker node key. * @param listener - The message listener callback. */ protected abstract deregisterWorkerMessageListener<Message extends Data | Response>(workerNodeKey: number, listener: (message: MessageValue<Message>) => void): void; /** * Terminates the worker node given its worker node key. * @param workerNodeKey - The worker node key. */ protected destroyWorkerNode(workerNodeKey: number): Promise<void>; protected flagWorkerNodeAsNotReady(workerNodeKey: number): void; protected flushTasksQueue(workerNodeKey: number): number; /** * Gets the worker information given its worker node key. * @param workerNodeKey - The worker node key. * @returns The worker information. */ protected getWorkerI