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