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