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