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