fix: refine type definition for transferList
[poolifier.git] / src / pools / pool.ts
CommitLineData
c3719753 1import type { ClusterSettings } from 'node:cluster'
ded253e2
JB
2import type { EventEmitterAsyncResource } from 'node:events'
3import type { TransferListItem, WorkerOptions } from 'node:worker_threads'
4
d35e5717 5import type { TaskFunction } from '../worker/task-functions.js'
ded253e2
JB
6import type {
7 WorkerChoiceStrategy,
8 WorkerChoiceStrategyOptions
9} from './selection-strategies/selection-strategies-types.js'
bdaf31cd
JB
10import type {
11 ErrorHandler,
12 ExitHandler,
50e66724 13 IWorker,
4b628b48 14 IWorkerNode,
bdaf31cd 15 MessageHandler,
c4855468 16 OnlineHandler,
4b628b48 17 WorkerType
d35e5717 18} from './worker.js'
bdaf31cd 19
c4855468 20/**
6b27d407 21 * Enumeration of pool types.
c4855468 22 */
59776ec5
JB
23export const PoolTypes: Readonly<{
24 fixed: 'fixed'
25 dynamic: 'dynamic'
26}> = Object.freeze({
c4855468
JB
27 /**
28 * Fixed pool type.
29 */
6b27d407 30 fixed: 'fixed',
c4855468
JB
31 /**
32 * Dynamic pool type.
33 */
6b27d407
JB
34 dynamic: 'dynamic'
35} as const)
36
37/**
38 * Pool type.
39 */
40export type PoolType = keyof typeof PoolTypes
c4855468 41
aee46736
JB
42/**
43 * Enumeration of pool events.
44 */
59776ec5
JB
45export const PoolEvents: Readonly<{
46 ready: 'ready'
47 busy: 'busy'
48 full: 'full'
49 empty: 'empty'
50 destroy: 'destroy'
51 error: 'error'
52 taskError: 'taskError'
53 backPressure: 'backPressure'
54}> = Object.freeze({
2431bdb4 55 ready: 'ready',
1f68cede 56 busy: 'busy',
ef3891a3 57 full: 'full',
8e8d9101 58 empty: 'empty',
ef3891a3 59 destroy: 'destroy',
91ee39ed 60 error: 'error',
671d5154
JB
61 taskError: 'taskError',
62 backPressure: 'backPressure'
aee46736
JB
63} as const)
64
65/**
66 * Pool event.
67 */
68export type PoolEvent = keyof typeof PoolEvents
69
6b27d407
JB
70/**
71 * Pool information.
72 */
73export interface PoolInfo {
4b628b48
JB
74 readonly version: string
75 readonly type: PoolType
76 readonly worker: WorkerType
47352846 77 readonly started: boolean
2431bdb4
JB
78 readonly ready: boolean
79 readonly strategy: WorkerChoiceStrategy
0e8587d2 80 readonly strategyRetries: number
4b628b48
JB
81 readonly minSize: number
82 readonly maxSize: number
aa9eede8 83 /** Pool utilization. */
4b628b48 84 readonly utilization?: number
01a59f3c 85 /** Pool total worker nodes. */
4b628b48 86 readonly workerNodes: number
5eb72b9e
JB
87 /** Pool stealing worker nodes. */
88 readonly stealingWorkerNodes?: number
01a59f3c 89 /** Pool idle worker nodes. */
4b628b48 90 readonly idleWorkerNodes: number
01a59f3c 91 /** Pool busy worker nodes. */
4b628b48
JB
92 readonly busyWorkerNodes: number
93 readonly executedTasks: number
94 readonly executingTasks: number
daf86646
JB
95 readonly queuedTasks?: number
96 readonly maxQueuedTasks?: number
a1763c54 97 readonly backPressure?: boolean
68cbdc84 98 readonly stolenTasks?: number
4b628b48
JB
99 readonly failedTasks: number
100 readonly runTime?: {
101 readonly minimum: number
102 readonly maximum: number
3baa0837 103 readonly average?: number
4b628b48 104 readonly median?: number
1dcf8b7b 105 }
4b628b48
JB
106 readonly waitTime?: {
107 readonly minimum: number
108 readonly maximum: number
3baa0837 109 readonly average?: number
4b628b48 110 readonly median?: number
1dcf8b7b 111 }
6b27d407
JB
112}
113
7171d33f 114/**
20c6f652 115 * Worker node tasks queue options.
7171d33f
JB
116 */
117export interface TasksQueueOptions {
118 /**
20c6f652
JB
119 * Maximum tasks queue size per worker node flagging it as back pressured.
120 *
121 * @defaultValue (pool maximum size)^2
122 */
ff3f866a 123 readonly size?: number
20c6f652
JB
124 /**
125 * Maximum number of tasks that can be executed concurrently on a worker node.
7171d33f
JB
126 *
127 * @defaultValue 1
128 */
eb7bf744 129 readonly concurrency?: number
47352846 130 /**
65542a35 131 * Whether to enable task stealing on idle.
47352846
JB
132 *
133 * @defaultValue true
134 */
dbd73092 135 readonly taskStealing?: boolean
47352846 136 /**
af98b972 137 * Whether to enable tasks stealing under back pressure.
47352846
JB
138 *
139 * @defaultValue true
140 */
141 readonly tasksStealingOnBackPressure?: boolean
32b141fd
JB
142 /**
143 * Queued tasks finished timeout in milliseconds at worker node termination.
144 *
653eba19 145 * @defaultValue 2000
32b141fd
JB
146 */
147 readonly tasksFinishedTimeout?: number
7171d33f
JB
148}
149
bdaf31cd
JB
150/**
151 * Options for a poolifier pool.
c319c66b 152 *
d480d708 153 * @typeParam Worker - Type of worker.
bdaf31cd 154 */
50e66724 155export interface PoolOptions<Worker extends IWorker> {
fd04474e
JB
156 /**
157 * A function that will listen for online event on each worker.
68f1f531
JB
158 *
159 * @defaultValue `() => {}`
fd04474e
JB
160 */
161 onlineHandler?: OnlineHandler<Worker>
bdaf31cd
JB
162 /**
163 * A function that will listen for message event on each worker.
68f1f531
JB
164 *
165 * @defaultValue `() => {}`
bdaf31cd
JB
166 */
167 messageHandler?: MessageHandler<Worker>
168 /**
169 * A function that will listen for error event on each worker.
68f1f531
JB
170 *
171 * @defaultValue `() => {}`
bdaf31cd
JB
172 */
173 errorHandler?: ErrorHandler<Worker>
bdaf31cd
JB
174 /**
175 * A function that will listen for exit event on each worker.
68f1f531
JB
176 *
177 * @defaultValue `() => {}`
bdaf31cd
JB
178 */
179 exitHandler?: ExitHandler<Worker>
47352846
JB
180 /**
181 * Whether to start the minimum number of workers at pool initialization.
182 *
8ff61e33 183 * @defaultValue true
47352846
JB
184 */
185 startWorkers?: boolean
bdaf31cd 186 /**
46e857ca 187 * The worker choice strategy to use in this pool.
d29bce7c 188 *
95ec6006 189 * @defaultValue WorkerChoiceStrategies.ROUND_ROBIN
bdaf31cd
JB
190 */
191 workerChoiceStrategy?: WorkerChoiceStrategy
da309861
JB
192 /**
193 * The worker choice strategy options.
194 */
195 workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions
1f68cede
JB
196 /**
197 * Restart worker on error.
198 */
199 restartWorkerOnError?: boolean
bdaf31cd 200 /**
b5604034 201 * Pool events integrated with async resource emission.
bdaf31cd 202 *
38e795c1 203 * @defaultValue true
bdaf31cd
JB
204 */
205 enableEvents?: boolean
ff733df7 206 /**
20c6f652 207 * Pool worker node tasks queue.
ff733df7 208 *
ff733df7
JB
209 * @defaultValue false
210 */
211 enableTasksQueue?: boolean
7171d33f 212 /**
20c6f652 213 * Pool worker node tasks queue options.
7171d33f
JB
214 */
215 tasksQueueOptions?: TasksQueueOptions
c3719753
JB
216 /**
217 * Worker options.
218 *
219 * @see https://nodejs.org/api/worker_threads.html#new-workerfilename-options
220 */
221 workerOptions?: WorkerOptions
222 /**
223 * Key/value pairs to add to worker process environment.
224 *
225 * @see https://nodejs.org/api/cluster.html#cluster_cluster_fork_env
226 */
227 env?: Record<string, unknown>
228 /**
229 * Cluster settings.
230 *
231 * @see https://nodejs.org/api/cluster.html#cluster_cluster_settings
232 */
233 settings?: ClusterSettings
bdaf31cd 234}
a35560ba 235
729c563d
S
236/**
237 * Contract definition for a poolifier pool.
238 *
c4855468 239 * @typeParam Worker - Type of worker which manages this pool.
e102732c
JB
240 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
241 * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
729c563d 242 */
c4855468
JB
243export interface IPool<
244 Worker extends IWorker,
245 Data = unknown,
246 Response = unknown
247> {
08f3f44c 248 /**
6b27d407 249 * Pool information.
08f3f44c 250 */
6b27d407 251 readonly info: PoolInfo
c4855468
JB
252 /**
253 * Pool worker nodes.
9768f49f
JB
254 *
255 * @internal
c4855468 256 */
4b628b48 257 readonly workerNodes: Array<IWorkerNode<Worker, Data>>
b4904890 258 /**
d67bed32 259 * Pool event emitter integrated with async resource.
b5604034 260 * The async tracking tooling identifier is `poolifier:<PoolType>-<WorkerType>-pool`.
b4904890
JB
261 *
262 * Events that can currently be listened to:
263 *
8e8d9101 264 * - `'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 is set to zero, this event is emitted when at least one dynamic worker is ready.
a9780ad2 265 * - `'busy'`: Emitted when the number of workers created in the pool has reached the maximum size expected and are executing concurrently their tasks quota.
ef3891a3 266 * - `'full'`: Emitted when the pool is dynamic and the number of workers created has reached the maximum size expected.
8e8d9101 267 * - `'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.
033f1776 268 * - `'destroy'`: Emitted when the pool is destroyed.
91ee39ed
JB
269 * - `'error'`: Emitted when an uncaught error occurs.
270 * - `'taskError'`: Emitted when an error occurs while executing a task.
d92f3ddf 271 * - `'backPressure'`: Emitted when all worker nodes have back pressure (i.e. their tasks queue is full: queue size \>= maximum queue size).
b4904890 272 */
f80125ca 273 readonly emitter?: EventEmitterAsyncResource
729c563d 274 /**
61aa11a6 275 * Executes the specified function in the worker constructor with the task data input parameter.
729c563d 276 *
7d91a8cd
JB
277 * @param data - The optional task input data for the specified task function. This can only be structured-cloneable data.
278 * @param name - The optional name of the task function to execute. If not specified, the default task function will be executed.
7379799c 279 * @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.
ef41a6e6 280 * @returns Promise that will be fulfilled when the task is completed.
729c563d 281 */
7d91a8cd
JB
282 readonly execute: (
283 data?: Data,
284 name?: string,
6a3ecc50 285 transferList?: readonly TransferListItem[]
7d91a8cd 286 ) => Promise<Response>
47352846
JB
287 /**
288 * Starts the minimum number of workers in this pool.
289 */
290 readonly start: () => void
280c2a77 291 /**
aa9eede8 292 * Terminates all workers in this pool.
280c2a77 293 */
4b628b48 294 readonly destroy: () => Promise<void>
6703b9f4
JB
295 /**
296 * Whether the specified task function exists in this pool.
297 *
298 * @param name - The name of the task function.
299 * @returns `true` if the task function exists, `false` otherwise.
300 */
301 readonly hasTaskFunction: (name: string) => boolean
302 /**
303 * Adds a task function to this pool.
304 * If a task function with the same name already exists, it will be overwritten.
305 *
306 * @param name - The name of the task function.
3feeab69 307 * @param fn - The task function.
6703b9f4 308 * @returns `true` if the task function was added, `false` otherwise.
cf87987c
JB
309 * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string or an empty string.
310 * @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `fn` parameter is not a function.
6703b9f4
JB
311 */
312 readonly addTaskFunction: (
313 name: string,
3feeab69 314 fn: TaskFunction<Data, Response>
e81c38f2 315 ) => Promise<boolean>
6703b9f4
JB
316 /**
317 * Removes a task function from this pool.
318 *
319 * @param name - The name of the task function.
320 * @returns `true` if the task function was removed, `false` otherwise.
321 */
e81c38f2 322 readonly removeTaskFunction: (name: string) => Promise<boolean>
90d7d101
JB
323 /**
324 * Lists the names of task function available in this pool.
325 *
326 * @returns The names of task function available in this pool.
327 */
6703b9f4
JB
328 readonly listTaskFunctionNames: () => string[]
329 /**
330 * Sets the default task function in this pool.
331 *
332 * @param name - The name of the task function.
333 * @returns `true` if the default task function was set, `false` otherwise.
334 */
e81c38f2 335 readonly setDefaultTaskFunction: (name: string) => Promise<boolean>
a35560ba 336 /**
bdede008 337 * Sets the worker choice strategy in this pool.
a35560ba 338 *
38e795c1 339 * @param workerChoiceStrategy - The worker choice strategy.
59219cbb 340 * @param workerChoiceStrategyOptions - The worker choice strategy options.
a35560ba 341 */
4b628b48 342 readonly setWorkerChoiceStrategy: (
59219cbb
JB
343 workerChoiceStrategy: WorkerChoiceStrategy,
344 workerChoiceStrategyOptions?: WorkerChoiceStrategyOptions
345 ) => void
a20f0ba5
JB
346 /**
347 * Sets the worker choice strategy options in this pool.
348 *
349 * @param workerChoiceStrategyOptions - The worker choice strategy options.
350 */
4b628b48 351 readonly setWorkerChoiceStrategyOptions: (
a20f0ba5
JB
352 workerChoiceStrategyOptions: WorkerChoiceStrategyOptions
353 ) => void
354 /**
20c6f652 355 * Enables/disables the worker node tasks queue in this pool.
a20f0ba5 356 *
20c6f652
JB
357 * @param enable - Whether to enable or disable the worker node tasks queue.
358 * @param tasksQueueOptions - The worker node tasks queue options.
a20f0ba5 359 */
4b628b48 360 readonly enableTasksQueue: (
8f52842f
JB
361 enable: boolean,
362 tasksQueueOptions?: TasksQueueOptions
363 ) => void
a20f0ba5 364 /**
20c6f652 365 * Sets the worker node tasks queue options in this pool.
a20f0ba5 366 *
20c6f652 367 * @param tasksQueueOptions - The worker node tasks queue options.
a20f0ba5 368 */
4b628b48 369 readonly setTasksQueueOptions: (tasksQueueOptions: TasksQueueOptions) => void
c97c7edb 370}