Merge branch 'master' into combined-prs-branch
[poolifier.git] / src / pools / worker.ts
CommitLineData
e1c2dba7 1import type { EventEmitter } from 'node:events'
ded253e2
JB
2import type { MessageChannel, WorkerOptions } from 'node:worker_threads'
3
f12182ad 4import type { CircularBuffer } from '../circular-buffer.js'
31847469 5import type { Task, TaskFunctionProperties } from '../utility-types.js'
f06e48d8 6
671d5154
JB
7/**
8 * Callback invoked when the worker has started successfully.
09b75fef
JB
9 *
10 * @typeParam Worker - Type of worker.
671d5154
JB
11 */
12export type OnlineHandler<Worker extends IWorker> = (this: Worker) => void
13
bdaf31cd
JB
14/**
15 * Callback invoked if the worker has received a message.
09b75fef
JB
16 *
17 * @typeParam Worker - Type of worker.
bdaf31cd 18 */
50e66724
JB
19export type MessageHandler<Worker extends IWorker> = (
20 this: Worker,
e102732c 21 message: unknown
50e66724 22) => void
bdaf31cd
JB
23
24/**
25 * Callback invoked if the worker raised an error.
09b75fef
JB
26 *
27 * @typeParam Worker - Type of worker.
bdaf31cd 28 */
50e66724
JB
29export type ErrorHandler<Worker extends IWorker> = (
30 this: Worker,
e102732c 31 error: Error
50e66724 32) => void
bdaf31cd 33
bdaf31cd
JB
34/**
35 * Callback invoked when the worker exits successfully.
09b75fef
JB
36 *
37 * @typeParam Worker - Type of worker.
bdaf31cd 38 */
50e66724
JB
39export type ExitHandler<Worker extends IWorker> = (
40 this: Worker,
e102732c 41 exitCode: number
50e66724 42) => void
bdaf31cd 43
3bcbd4c5
JB
44/**
45 * Worker event handler.
46 *
47 * @typeParam Worker - Type of worker.
48 */
49export type EventHandler<Worker extends IWorker> =
50 | OnlineHandler<Worker>
51 | MessageHandler<Worker>
52 | ErrorHandler<Worker>
53 | ExitHandler<Worker>
54
f12182ad
JB
55/**
56 * Measurement history size.
57 */
58export const MeasurementHistorySize = 386
59
f06e48d8 60/**
cd4d348a 61 * Measurement statistics.
f9b4bbf8
JB
62 *
63 * @internal
f06e48d8 64 */
cd4d348a 65export interface MeasurementStatistics {
02706357 66 /**
932fc8be 67 * Measurement aggregate.
02706357 68 */
71514351 69 aggregate?: number
f7510105
JB
70 /**
71 * Measurement minimum.
72 */
71514351 73 minimum?: number
f7510105
JB
74 /**
75 * Measurement maximum.
76 */
71514351 77 maximum?: number
02706357 78 /**
cd4d348a 79 * Measurement average.
02706357 80 */
71514351 81 average?: number
02706357 82 /**
cd4d348a 83 * Measurement median.
02706357 84 */
71514351 85 median?: number
02706357 86 /**
cd4d348a 87 * Measurement history.
02706357 88 */
0cd1f28c 89 readonly history: CircularBuffer
a4e07f72
JB
90}
91
5df69fab
JB
92/**
93 * Event loop utilization measurement statistics.
94 *
95 * @internal
96 */
97export interface EventLoopUtilizationMeasurementStatistics {
eb7bf744
JB
98 readonly idle: MeasurementStatistics
99 readonly active: MeasurementStatistics
f7510105 100 utilization?: number
5df69fab
JB
101}
102
a4e07f72
JB
103/**
104 * Task statistics.
105 *
106 * @internal
107 */
a4e07f72 108export interface TaskStatistics {
02706357 109 /**
9a0613e9 110 * Number of executed tasks.
02706357 111 */
a4e07f72 112 executed: number
02706357 113 /**
9a0613e9 114 * Number of executing tasks.
02706357 115 */
a4e07f72 116 executing: number
0567595a 117 /**
9a0613e9 118 * Number of queued tasks.
0567595a 119 */
8604aaab 120 readonly queued: number
df593701
JB
121 /**
122 * Maximum number of queued tasks.
123 */
b25a42cd 124 readonly maxQueued?: number
463226a4
JB
125 /**
126 * Number of sequentially stolen tasks.
127 */
128 sequentiallyStolen: number
68cbdc84
JB
129 /**
130 * Number of stolen tasks.
131 */
132 stolen: number
0567595a 133 /**
9a0613e9 134 * Number of failed tasks.
0567595a 135 */
a4e07f72
JB
136 failed: number
137}
138
4b628b48
JB
139/**
140 * Enumeration of worker types.
141 */
59776ec5
JB
142export const WorkerTypes: Readonly<{ thread: 'thread', cluster: 'cluster' }> =
143 Object.freeze({
144 thread: 'thread',
145 cluster: 'cluster'
146 } as const)
4b628b48
JB
147
148/**
149 * Worker type.
150 */
151export type WorkerType = keyof typeof WorkerTypes
152
f59e1027
JB
153/**
154 * Worker information.
155 *
156 * @internal
157 */
158export interface WorkerInfo {
159 /**
83fa0a36 160 * Worker id.
f59e1027 161 */
eb7bf744 162 readonly id: number | undefined
4b628b48
JB
163 /**
164 * Worker type.
165 */
5b49e864 166 readonly type: WorkerType
8a1260a3
JB
167 /**
168 * Dynamic flag.
169 */
170 dynamic: boolean
f59e1027 171 /**
7c8381eb 172 * Ready flag.
f59e1027 173 */
7c8381eb 174 ready: boolean
5eb72b9e
JB
175 /**
176 * Stealing flag.
177 * This flag is set to `true` when worker node is stealing tasks from another worker node.
178 */
179 stealing: boolean
2eee7220
JB
180 /**
181 * Back pressure flag.
182 * This flag is set to `true` when worker node tasks queue has back pressure.
183 */
184 backPressure: boolean
b558f6b5 185 /**
31847469 186 * Task functions properties.
b558f6b5 187 */
31847469 188 taskFunctionsProperties?: TaskFunctionProperties[]
f59e1027
JB
189}
190
a4e07f72
JB
191/**
192 * Worker usage statistics.
193 *
194 * @internal
195 */
196export interface WorkerUsage {
0567595a 197 /**
a4e07f72 198 * Tasks statistics.
0567595a 199 */
eb7bf744 200 readonly tasks: TaskStatistics
0567595a 201 /**
a4e07f72 202 * Tasks runtime statistics.
0567595a 203 */
eb7bf744 204 readonly runTime: MeasurementStatistics
02706357 205 /**
a4e07f72 206 * Tasks wait time statistics.
02706357 207 */
eb7bf744 208 readonly waitTime: MeasurementStatistics
62c15a68 209 /**
5df69fab 210 * Tasks event loop utilization statistics.
62c15a68 211 */
eb7bf744 212 readonly elu: EventLoopUtilizationMeasurementStatistics
f06e48d8
JB
213}
214
f3a91bac 215/**
9df180cb 216 * Worker choice strategy data.
57a29f75
JB
217 *
218 * @internal
f3a91bac
JB
219 */
220export interface StrategyData {
221 virtualTaskEndTimestamp?: number
222}
223
f06e48d8
JB
224/**
225 * Worker interface.
226 */
a4791fb1 227export interface IWorker extends EventEmitter {
f59e1027 228 /**
07e0c9e5 229 * Cluster worker id.
f59e1027 230 */
aecc6e48 231 readonly id?: number
07e0c9e5
JB
232 /**
233 * Worker thread worker id.
234 */
aecc6e48 235 readonly threadId?: number
bdaf31cd 236 /**
88af9bf1 237 * Registers an event handler.
bdaf31cd 238 *
38e795c1 239 * @param event - The event.
48ef9107 240 * @param handler - The event handler.
bdaf31cd 241 */
a4791fb1 242 readonly on: (event: string, handler: EventHandler<this>) => this
c3719753 243 /**
88af9bf1 244 * Registers once an event handler.
bdaf31cd 245 *
c3719753
JB
246 * @param event - The event.
247 * @param handler - The event handler.
bdaf31cd 248 */
a4791fb1 249 readonly once: (event: string, handler: EventHandler<this>) => this
d20cde84
JB
250 /**
251 * Calling `unref()` on a worker allows the thread to exit if this is the only
252 * active handle in the event system. If the worker is already `unref()`ed calling`unref()` again has no effect.
253 * @since v10.5.0
254 */
255 readonly unref?: () => void
07e0c9e5
JB
256 /**
257 * Stop all JavaScript execution in the worker thread as soon as possible.
258 * Returns a Promise for the exit code that is fulfilled when the `'exit' event` is emitted.
259 */
260 readonly terminate?: () => Promise<number>
261 /**
262 * Cluster worker disconnect.
263 */
264 readonly disconnect?: () => void
265 /**
266 * Cluster worker kill.
267 */
268 readonly kill?: (signal?: string) => void
bdaf31cd 269}
f06e48d8 270
5b49e864 271/**
c3719753 272 * Worker node options.
5b49e864 273 *
5b49e864
JB
274 * @internal
275 */
c3719753
JB
276export interface WorkerNodeOptions {
277 workerOptions?: WorkerOptions
278 env?: Record<string, unknown>
c63a35a0 279 tasksQueueBackPressureSize: number | undefined
95d1a734 280 tasksQueueBucketSize: number | undefined
fcfc3353 281 tasksQueuePriority: boolean | undefined
9f95d5eb 282}
ec287edf 283
f06e48d8
JB
284/**
285 * Worker node interface.
c319c66b
JB
286 *
287 * @typeParam Worker - Type of worker.
e102732c 288 * @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data.
c319c66b 289 * @internal
f06e48d8 290 */
9f95d5eb 291export interface IWorkerNode<Worker extends IWorker, Data = unknown>
e1c2dba7 292 extends EventEmitter {
c319c66b 293 /**
ccd73e07 294 * Worker.
c319c66b 295 */
02706357 296 readonly worker: Worker
f59e1027 297 /**
ccd73e07 298 * Worker info.
f59e1027 299 */
eb7bf744 300 readonly info: WorkerInfo
c319c66b 301 /**
ccd73e07 302 * Worker usage statistics.
c319c66b 303 */
5b49e864 304 readonly usage: WorkerUsage
f3a91bac 305 /**
9df180cb 306 * Worker choice strategy data.
ae3ab61d 307 * This is used to store data that are specific to the worker choice strategy.
f3a91bac
JB
308 */
309 strategyData?: StrategyData
26fb3c18 310 /**
07e0c9e5 311 * Message channel (worker thread only).
26fb3c18
JB
312 */
313 readonly messageChannel?: MessageChannel
20c6f652
JB
314 /**
315 * Tasks queue back pressure size.
316 * This is the number of tasks that can be enqueued before the worker node has back pressure.
317 */
318 tasksQueueBackPressureSize: number
fcfc3353
JB
319 /**
320 * Sets tasks queue priority.
321 *
322 * @param enablePriority - Whether to enable tasks queue priority.
323 */
324 readonly setTasksQueuePriority: (enablePriority: boolean) => void
c319c66b 325 /**
ccd73e07 326 * Tasks queue size.
4b628b48
JB
327 *
328 * @returns The tasks queue size.
329 */
330 readonly tasksQueueSize: () => number
331 /**
ccd73e07 332 * Enqueue task.
4b628b48
JB
333 *
334 * @param task - The task to queue.
a1763c54 335 * @returns The tasks queue size.
4b628b48
JB
336 */
337 readonly enqueueTask: (task: Task<Data>) => number
338 /**
ccd73e07 339 * Dequeue task.
4b628b48 340 *
95d1a734 341 * @param bucket - The prioritized bucket to dequeue from. @defaultValue 0
4b628b48
JB
342 * @returns The dequeued task.
343 */
95d1a734 344 readonly dequeueTask: (bucket?: number) => Task<Data> | undefined
0d4e88b3 345 /**
2eee7220 346 * Dequeue last prioritized task.
0d4e88b3
JB
347 *
348 * @returns The dequeued task.
349 */
2eee7220 350 readonly dequeueLastPrioritizedTask: () => Task<Data> | undefined
4b628b48 351 /**
ccd73e07 352 * Clears tasks queue.
4b628b48
JB
353 */
354 readonly clearTasksQueue: () => void
671d5154 355 /**
e2b31e32 356 * Whether the worker node has back pressure (i.e. its tasks queue is full).
671d5154
JB
357 *
358 * @returns `true` if the worker node has back pressure, `false` otherwise.
359 */
360 readonly hasBackPressure: () => boolean
3f09ed9f 361 /**
07e0c9e5 362 * Terminates the worker node.
3f09ed9f 363 */
07e0c9e5 364 readonly terminate: () => Promise<void>
c3719753
JB
365 /**
366 * Registers a worker event handler.
367 *
368 * @param event - The event.
88af9bf1 369 * @param handler - The event handler.
c3719753
JB
370 */
371 readonly registerWorkerEventHandler: (
372 event: string,
3bcbd4c5 373 handler: EventHandler<Worker>
c3719753
JB
374 ) => void
375 /**
376 * Registers once a worker event handler.
377 *
378 * @param event - The event.
88af9bf1 379 * @param handler - The event handler.
c3719753
JB
380 */
381 readonly registerOnceWorkerEventHandler: (
382 event: string,
3bcbd4c5 383 handler: EventHandler<Worker>
c3719753 384 ) => void
ff128cc9 385 /**
2809112e
JB
386 * Gets task function worker usage statistics.
387 *
388 * @param name - The task function name.
389 * @returns The task function worker usage statistics if the task function worker usage statistics are initialized, `undefined` otherwise.
ff128cc9 390 */
db0e38ee 391 readonly getTaskFunctionWorkerUsage: (name: string) => WorkerUsage | undefined
adee6053
JB
392 /**
393 * Deletes task function worker usage statistics.
394 *
395 * @param name - The task function name.
396 * @returns `true` if the task function worker usage statistics were deleted, `false` otherwise.
397 */
398 readonly deleteTaskFunctionWorkerUsage: (name: string) => boolean
f06e48d8 399}
c3719753
JB
400
401/**
402 * Worker node event detail.
403 *
404 * @internal
405 */
406export interface WorkerNodeEventDetail {
3a20a1a1 407 workerId?: number
c3719753
JB
408 workerNodeKey?: number
409}