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