poolifier 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -156,14 +156,18 @@ You can use node versions >= 12.x for thread pool, and node versions >= 16.x for
156
156
  `filePath` (mandatory) Path to a file with a worker implementation
157
157
  `opts` (optional) An object with these properties:
158
158
 
159
+ - `messageHandler` (optional) - A function that will listen for message event on each worker
159
160
  - `errorHandler` (optional) - A function that will listen for error event on each worker
160
161
  - `onlineHandler` (optional) - A function that will listen for online event on each worker
161
162
  - `exitHandler` (optional) - A function that will listen for exit event on each worker
162
- - `workerChoiceStrategy` (optional) - The work choice strategy to use in this pool:
163
+ - `workerChoiceStrategy` (optional) - The worker choice strategy to use in this pool:
163
164
 
164
- - `WorkerChoiceStrategies.ROUND_ROBIN`: Submit tasks to worker in this pool in a round robbin fashion
165
- - `WorkerChoiceStrategies.LESS_RECENTLY_USED`: Submit tasks to the less recently used worker in the pool
165
+ - `WorkerChoiceStrategies.ROUND_ROBIN`: Submit tasks to worker in a round robbin fashion
166
+ - `WorkerChoiceStrategies.LESS_RECENTLY_USED`: Submit tasks to the less recently used worker
167
+ - `WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN` Submit tasks to worker using a weighted round robin scheduling algorithm based on tasks execution time
168
+ - `WorkerChoiceStrategies.FAIR_SHARE`: Submit tasks to worker using a fair share tasks scheduling algorithm based on tasks execution time
166
169
 
170
+ `WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN` and `WorkerChoiceStrategies.FAIR_SHARE` strategies are targeted to heavy and long tasks
167
171
  Default: `WorkerChoiceStrategies.ROUND_ROBIN`
168
172
 
169
173
  - `enableEvents` (optional) - Events emission enablement in this pool. Default: true
@@ -194,9 +198,9 @@ This method will call the terminate method on each worker.
194
198
  The last active time of your worker unit will be updated when a task is submitted to a worker or when a worker terminate a task.
195
199
  If `killBehavior` is set to `KillBehaviors.HARD` this value represents also the timeout for the tasks that you submit to the pool, when this timeout expires your tasks is interrupted and the worker is killed if is not part of the minimum size of the pool.
196
200
  If `killBehavior` is set to `KillBehaviors.SOFT` your tasks have no timeout and your workers will not be terminated until your task is completed.
197
- Default: 60.000 ms
201
+ Default: 60000 ms
198
202
 
199
- - `async` - true/false, true if your function contains async pieces else false
203
+ - `async` - true/false, true if your function contains async code pieces, else false
200
204
  - `killBehavior` - Dictates if your async unit (worker/process) will be deleted in case that a task is active on it.
201
205
  **KillBehaviors.SOFT**: If `currentTime - lastActiveTime` is greater than `maxInactiveTime` but a task is still running, then the worker **won't** be deleted.
202
206
  **KillBehaviors.HARD**: If `lastActiveTime` is greater than `maxInactiveTime` but a task is still running, then the worker will be deleted.
@@ -244,7 +248,7 @@ But in general, **always profile your application**
244
248
  ## Contribute
245
249
 
246
250
  See guidelines [CONTRIBUTING](CONTRIBUTING.md)
247
- Choose your task here [2.0.0](https://github.com/poolifier/poolifier/projects/1), propose an idea, a fix, an improvement.
251
+ Choose your task here [2.3.0](https://github.com/orgs/poolifier/projects/1), propose an idea, a fix, an improvement.
248
252
 
249
253
  ## Team
250
254
 
package/lib/index.d.ts CHANGED
@@ -30,7 +30,7 @@ interface WorkerOptions {
30
30
  * when this timeout expires your tasks is interrupted and the worker is killed if is not part of the minimum size of the pool.
31
31
  * - If `killBehavior` is set to `KillBehaviors.SOFT` your tasks have no timeout and your workers will not be terminated until your task is completed.
32
32
  *
33
- * @default 60.000 ms
33
+ * @default 60000 ms
34
34
  */
35
35
  maxInactiveTime?: number;
36
36
  /**
@@ -77,6 +77,10 @@ interface MessageValue<Data = unknown, MainWorker extends ClusterWorker | Messag
77
77
  * Error.
78
78
  */
79
79
  readonly error?: string;
80
+ /**
81
+ * Task runtime.
82
+ */
83
+ readonly taskRunTime?: number;
80
84
  /**
81
85
  * Reference to main worker.
82
86
  *
@@ -90,7 +94,7 @@ interface MessageValue<Data = unknown, MainWorker extends ClusterWorker | Messag
90
94
  * @template Worker Type of worker.
91
95
  * @template Response Type of response of execution. This can only be serializable data.
92
96
  */
93
- interface PromiseWorkerResponseWrapper<Worker extends AbstractPoolWorker, Response = unknown> {
97
+ interface PromiseWorkerResponseWrapper<Worker extends IPoolWorker, Response = unknown> {
94
98
  /**
95
99
  * Resolve callback to fulfill the promise.
96
100
  */
@@ -121,13 +125,9 @@ type OnlineHandler<Worker> = (this: Worker) => void;
121
125
  */
122
126
  type ExitHandler<Worker> = (this: Worker, code: number) => void;
123
127
  /**
124
- * Basic interface that describes the minimum required implementation of listener events for a pool worker.
128
+ * Interface that describes the minimum required implementation of listener events for a pool worker.
125
129
  */
126
130
  interface IPoolWorker {
127
- /**
128
- * Worker identifier.
129
- */
130
- readonly id?: number;
131
131
  /**
132
132
  * Register a listener to the message event.
133
133
  *
@@ -164,32 +164,48 @@ interface IPoolWorker {
164
164
  */
165
165
  once(event: "exit", handler: ExitHandler<this>): void;
166
166
  }
167
- /**
168
- * Basic class that implement the minimum required for a pool worker.
169
- */
170
- declare abstract class AbstractPoolWorker implements IPoolWorker {
171
- /** @inheritDoc */
172
- abstract on(event: "message", handler: MessageHandler<this>): void;
173
- /** @inheritDoc */
174
- abstract on(event: "error", handler: ErrorHandler<this>): void;
175
- /** @inheritDoc */
176
- abstract on(event: "online", handler: OnlineHandler<this>): void;
177
- /** @inheritDoc */
178
- abstract on(event: "exit", handler: ExitHandler<this>): void;
179
- /** @inheritDoc */
180
- abstract once(event: "exit", handler: ExitHandler<this>): void;
181
- }
182
167
  /**
183
168
  * Enumeration of worker choice strategies.
184
169
  */
185
170
  declare const WorkerChoiceStrategies: Readonly<{
186
171
  readonly ROUND_ROBIN: "ROUND_ROBIN";
187
172
  readonly LESS_RECENTLY_USED: "LESS_RECENTLY_USED";
173
+ readonly FAIR_SHARE: "FAIR_SHARE";
174
+ readonly WEIGHTED_ROUND_ROBIN: "WEIGHTED_ROUND_ROBIN";
188
175
  }>;
189
176
  /**
190
177
  * Worker choice strategy.
191
178
  */
192
179
  type WorkerChoiceStrategy = keyof typeof WorkerChoiceStrategies;
180
+ /**
181
+ * Pool tasks usage statistics requirements.
182
+ */
183
+ type RequiredStatistics = {
184
+ runTime: boolean;
185
+ };
186
+ /**
187
+ * Worker choice strategy interface.
188
+ *
189
+ * @template Worker Type of worker which manages the strategy.
190
+ */
191
+ interface IWorkerChoiceStrategy<Worker extends IPoolWorker> {
192
+ /**
193
+ * Is the pool attached to the strategy dynamic?.
194
+ */
195
+ readonly isDynamicPool: boolean;
196
+ /**
197
+ * Required pool tasks usage statistics.
198
+ */
199
+ readonly requiredStatistics: RequiredStatistics;
200
+ /**
201
+ * Resets strategy internals (counters, statistics, etc.).
202
+ */
203
+ reset(): boolean;
204
+ /**
205
+ * Chooses a worker in the pool.
206
+ */
207
+ choose(): Worker;
208
+ }
193
209
  /**
194
210
  * Options for a poolifier pool.
195
211
  */
@@ -211,7 +227,7 @@ interface PoolOptions<Worker> {
211
227
  */
212
228
  exitHandler?: ExitHandler<Worker>;
213
229
  /**
214
- * The work choice strategy to use in this pool.
230
+ * The worker choice strategy to use in this pool.
215
231
  */
216
232
  workerChoiceStrategy?: WorkerChoiceStrategy;
217
233
  /**
@@ -229,18 +245,18 @@ interface PoolOptions<Worker> {
229
245
  */
230
246
  interface IPool<Data = unknown, Response = unknown> {
231
247
  /**
232
- * Perform the task specified in the constructor with the data parameter.
248
+ * Performs the task specified in the constructor with the data parameter.
233
249
  *
234
250
  * @param data The input for the specified task. This can only be serializable data.
235
251
  * @returns Promise that will be resolved when the task is successfully completed.
236
252
  */
237
253
  execute(data: Data): Promise<Response>;
238
254
  /**
239
- * Shut down every current worker in this pool.
255
+ * Shutdowns every current worker in this pool.
240
256
  */
241
257
  destroy(): Promise<void>;
242
258
  /**
243
- * Set the worker choice strategy in this pool.
259
+ * Sets the worker choice strategy in this pool.
244
260
  *
245
261
  * @param workerChoiceStrategy The worker choice strategy.
246
262
  */
@@ -253,6 +269,15 @@ declare enum PoolType {
253
269
  FIXED = "fixed",
254
270
  DYNAMIC = "dynamic"
255
271
  }
272
+ /**
273
+ * Tasks usage statistics.
274
+ */
275
+ interface TasksUsage {
276
+ run: number;
277
+ running: number;
278
+ runTime: number;
279
+ avgRunTime: number;
280
+ }
256
281
  /**
257
282
  * Internal poolifier pool emitter.
258
283
  */
@@ -265,18 +290,18 @@ declare class PoolEmitter extends EventEmitter {
265
290
  * @template Data Type of data sent to the worker.
266
291
  * @template Response Type of response of execution.
267
292
  */
268
- interface IPoolInternal<Worker extends AbstractPoolWorker, Data = unknown, Response = unknown> extends IPool<Data, Response> {
293
+ interface IPoolInternal<Worker extends IPoolWorker, Data = unknown, Response = unknown> extends IPool<Data, Response> {
269
294
  /**
270
295
  * List of currently available workers.
271
296
  */
272
297
  readonly workers: Worker[];
273
298
  /**
274
- * The tasks map.
299
+ * The workers tasks usage map.
275
300
  *
276
- * - `key`: The `Worker`
277
- * - `value`: Number of tasks currently in progress on the worker.
301
+ * `key`: The `Worker`
302
+ * `value`: Worker tasks usage statistics.
278
303
  */
279
- readonly tasks: Map<Worker, number>;
304
+ readonly workersTasksUsage: Map<Worker, TasksUsage>;
280
305
  /**
281
306
  * Emitter on which events can be listened to.
282
307
  *
@@ -329,6 +354,13 @@ interface IPoolInternal<Worker extends AbstractPoolWorker, Data = unknown, Respo
329
354
  * @returns The number of tasks currently running on the worker.
330
355
  */
331
356
  getWorkerRunningTasks(worker: Worker): number | undefined;
357
+ /**
358
+ * Get worker average tasks runtime.
359
+ *
360
+ * @param worker The worker.
361
+ * @returns The average tasks runtime on the worker.
362
+ */
363
+ getWorkerAverageTasksRunTime(worker: Worker): number | undefined;
332
364
  }
333
365
  /**
334
366
  * The worker choice strategy context.
@@ -337,7 +369,7 @@ interface IPoolInternal<Worker extends AbstractPoolWorker, Data = unknown, Respo
337
369
  * @template Data Type of data sent to the worker. This can only be serializable data.
338
370
  * @template Response Type of response of execution. This can only be serializable data.
339
371
  */
340
- declare class WorkerChoiceStrategyContext<Worker extends AbstractPoolWorker, Data, Response> {
372
+ declare class WorkerChoiceStrategyContext<Worker extends IPoolWorker, Data, Response> {
341
373
  private readonly pool;
342
374
  private createDynamicallyWorkerCallback;
343
375
  private workerChoiceStrategy;
@@ -350,40 +382,46 @@ declare class WorkerChoiceStrategyContext<Worker extends AbstractPoolWorker, Dat
350
382
  */
351
383
  constructor(pool: IPoolInternal<Worker, Data, Response>, createDynamicallyWorkerCallback: () => Worker, workerChoiceStrategy?: WorkerChoiceStrategy);
352
384
  /**
353
- * Get the worker choice strategy instance specific to the pool type.
385
+ * Gets the worker choice strategy instance specific to the pool type.
354
386
  *
355
387
  * @param workerChoiceStrategy The worker choice strategy.
356
388
  * @returns The worker choice strategy instance for the pool type.
357
389
  */
358
390
  private getPoolWorkerChoiceStrategy;
359
391
  /**
360
- * Set the worker choice strategy to use in the context.
392
+ * Gets the worker choice strategy used in the context.
393
+ *
394
+ * @returns The worker choice strategy.
395
+ */
396
+ getWorkerChoiceStrategy(): IWorkerChoiceStrategy<Worker>;
397
+ /**
398
+ * Sets the worker choice strategy to use in the context.
361
399
  *
362
400
  * @param workerChoiceStrategy The worker choice strategy to set.
363
401
  */
364
402
  setWorkerChoiceStrategy(workerChoiceStrategy: WorkerChoiceStrategy): void;
365
403
  /**
366
- * Choose a worker with the underlying selection strategy.
404
+ * Chooses a worker with the underlying selection strategy.
367
405
  *
368
406
  * @returns The chosen one.
369
407
  */
370
408
  execute(): Worker;
371
409
  }
372
410
  /**
373
- * Base class containing some shared logic for all poolifier pools.
411
+ * Base class that implements some shared logic for all poolifier pools.
374
412
  *
375
413
  * @template Worker Type of worker which manages this pool.
376
414
  * @template Data Type of data sent to the worker. This can only be serializable data.
377
415
  * @template Response Type of response of execution. This can only be serializable data.
378
416
  */
379
- declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = unknown, Response = unknown> implements IPoolInternal<Worker, Data, Response> {
417
+ declare abstract class AbstractPool<Worker extends IPoolWorker, Data = unknown, Response = unknown> implements IPoolInternal<Worker, Data, Response> {
380
418
  readonly numberOfWorkers: number;
381
419
  readonly filePath: string;
382
420
  readonly opts: PoolOptions<Worker>;
383
421
  /** @inheritDoc */
384
422
  readonly workers: Worker[];
385
423
  /** @inheritDoc */
386
- readonly tasks: Map<Worker, number>;
424
+ readonly workersTasksUsage: Map<Worker, TasksUsage>;
387
425
  /** @inheritDoc */
388
426
  readonly emitter?: PoolEmitter;
389
427
  /** @inheritDoc */
@@ -423,9 +461,11 @@ declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = un
423
461
  /** @inheritDoc */
424
462
  get numberOfRunningTasks(): number;
425
463
  /** @inheritDoc */
464
+ getWorkerIndex(worker: Worker): number;
465
+ /** @inheritDoc */
426
466
  getWorkerRunningTasks(worker: Worker): number | undefined;
427
467
  /** @inheritDoc */
428
- getWorkerIndex(worker: Worker): number;
468
+ getWorkerAverageTasksRunTime(worker: Worker): number | undefined;
429
469
  /** @inheritDoc */
430
470
  setWorkerChoiceStrategy(workerChoiceStrategy: WorkerChoiceStrategy): void;
431
471
  /** @inheritDoc */
@@ -438,7 +478,7 @@ declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = un
438
478
  /** @inheritDoc */
439
479
  destroy(): Promise<void>;
440
480
  /**
441
- * Shut down given worker.
481
+ * Shutdowns given worker.
442
482
  *
443
483
  * @param worker A worker within `workers`.
444
484
  */
@@ -453,24 +493,20 @@ declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = un
453
493
  */
454
494
  protected abstract isMain(): boolean;
455
495
  /**
456
- * Increase the number of tasks that the given worker has applied.
457
- *
458
- * @param worker Worker whose tasks are increased.
459
- */
460
- protected increaseWorkersTask(worker: Worker): void;
461
- /**
462
- * Decrease the number of tasks that the given worker has applied.
496
+ * Hook executed before the worker task promise resolution.
497
+ * Can be overridden.
463
498
  *
464
- * @param worker Worker whose tasks are decreased.
499
+ * @param worker The worker.
465
500
  */
466
- protected decreaseWorkersTasks(worker: Worker): void;
501
+ protected beforePromiseWorkerResponseHook(worker: Worker): void;
467
502
  /**
468
- * Step the number of tasks that the given worker has applied.
503
+ * Hook executed after the worker task promise resolution.
504
+ * Can be overridden.
469
505
  *
470
- * @param worker Worker whose tasks are set.
471
- * @param step Worker number of tasks step.
506
+ * @param message The received message.
507
+ * @param promise The Promise response.
472
508
  */
473
- private stepWorkerNumberOfTasks;
509
+ protected afterPromiseWorkerResponseHook(message: MessageValue<Response>, promise: PromiseWorkerResponseWrapper<Worker, Response>): void;
474
510
  /**
475
511
  * Removes the given worker from the pool.
476
512
  *
@@ -478,7 +514,7 @@ declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = un
478
514
  */
479
515
  protected removeWorker(worker: Worker): void;
480
516
  /**
481
- * Choose a worker for the next task.
517
+ * Chooses a worker for the next task.
482
518
  *
483
519
  * The default implementation uses a round robin algorithm to distribute the load.
484
520
  *
@@ -486,14 +522,14 @@ declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = un
486
522
  */
487
523
  protected chooseWorker(): Worker;
488
524
  /**
489
- * Send a message to the given worker.
525
+ * Sends a message to the given worker.
490
526
  *
491
527
  * @param worker The worker which should receive the message.
492
528
  * @param message The message.
493
529
  */
494
530
  protected abstract sendToWorker(worker: Worker, message: MessageValue<Data>): void;
495
531
  /**
496
- * Register a listener callback on a given worker.
532
+ * Registers a listener callback on a given worker.
497
533
  *
498
534
  * @param worker A worker.
499
535
  * @param listener A message listener callback.
@@ -525,6 +561,57 @@ declare abstract class AbstractPool<Worker extends AbstractPoolWorker, Data = un
525
561
  */
526
562
  protected workerListener(): (message: MessageValue<Response>) => void;
527
563
  private checkAndEmitBusy;
564
+ /**
565
+ * Increases the number of tasks that the given worker has applied.
566
+ *
567
+ * @param worker Worker which running tasks is increased.
568
+ */
569
+ private increaseWorkerRunningTasks;
570
+ /**
571
+ * Decreases the number of tasks that the given worker has applied.
572
+ *
573
+ * @param worker Worker which running tasks is decreased.
574
+ */
575
+ private decreaseWorkerRunningTasks;
576
+ /**
577
+ * Steps the number of tasks that the given worker has applied.
578
+ *
579
+ * @param worker Worker which running tasks are stepped.
580
+ * @param step Number of running tasks step.
581
+ */
582
+ private stepWorkerRunningTasks;
583
+ /**
584
+ * Steps the number of tasks that the given worker has run.
585
+ *
586
+ * @param worker Worker which has run tasks.
587
+ * @param step Number of run tasks step.
588
+ */
589
+ private stepWorkerRunTasks;
590
+ /**
591
+ * Updates tasks runtime for the given worker.
592
+ *
593
+ * @param worker Worker which run the task.
594
+ * @param taskRunTime Worker task runtime.
595
+ */
596
+ private updateWorkerTasksRunTime;
597
+ /**
598
+ * Initializes tasks usage statistics.
599
+ *
600
+ * @param worker The worker.
601
+ */
602
+ initWorkerTasksUsage(worker: Worker): void;
603
+ /**
604
+ * Removes worker tasks usage statistics.
605
+ *
606
+ * @param worker The worker.
607
+ */
608
+ private removeWorkerTasksUsage;
609
+ /**
610
+ * Resets worker tasks usage statistics.
611
+ *
612
+ * @param worker The worker.
613
+ */
614
+ private resetWorkerTasksUsage;
528
615
  }
529
616
  /**
530
617
  * Options for a poolifier cluster pool.
@@ -676,7 +763,7 @@ declare class DynamicThreadPool<Data = unknown, Response = unknown> extends Fixe
676
763
  get busy(): boolean;
677
764
  }
678
765
  /**
679
- * Base class containing some shared logic for all poolifier workers.
766
+ * Base class that implements some shared logic for all poolifier workers.
680
767
  *
681
768
  * @template MainWorker Type of main worker.
682
769
  * @template Data Type of data this worker receives from pool's execution. This can only be serializable data.
@@ -805,4 +892,4 @@ declare class ThreadWorker<Data = unknown, Response = unknown> extends AbstractW
805
892
  protected sendToMainWorker(message: MessageValue<Response>): void;
806
893
  }
807
894
  export { DynamicClusterPool, FixedClusterPool, WorkerChoiceStrategies, DynamicThreadPool, FixedThreadPool, AbstractWorker, ClusterWorker$0 as ClusterWorker, ThreadWorker, KillBehaviors };
808
- export type { ClusterPoolOptions, IPool, PoolOptions, ErrorHandler, ExitHandler, IPoolWorker, OnlineHandler, WorkerChoiceStrategy, ThreadWorkerWithMessageChannel, KillBehavior, WorkerOptions };
895
+ export type { ClusterPoolOptions, IPool, PoolOptions, ErrorHandler, ExitHandler, IPoolWorker, MessageHandler, OnlineHandler, WorkerChoiceStrategy, ThreadWorkerWithMessageChannel, KillBehavior, WorkerOptions };
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("events"),r=require("cluster"),t=require("worker_threads"),s=require("async_hooks");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i,n=o(e),a=o(r);!function(e){e.FIXED="fixed",e.DYNAMIC="dynamic"}(i||(i={}));class h extends n.default{}const c=()=>{},l=Object.freeze({SOFT:"SOFT",HARD:"HARD"});const k=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LESS_RECENTLY_USED:"LESS_RECENTLY_USED"});class u{constructor(e){this.pool=e,this.isDynamicPool=this.pool.type===i.DYNAMIC}}class p extends u{choose(){let e,r=1/0;for(const t of this.pool.workers){const s=this.pool.getWorkerRunningTasks(t);if(!1===this.isDynamicPool&&0===s)return t;s<r&&(e=t,r=s)}return e}}class d extends u{constructor(){super(...arguments),this.nextWorkerIndex=0}choose(){const e=this.pool.workers[this.nextWorkerIndex];return this.nextWorkerIndex=this.nextWorkerIndex===this.pool.workers.length-1?0:this.nextWorkerIndex+1,e}}class W{static getWorkerChoiceStrategy(e,r=k.ROUND_ROBIN){switch(r){case k.ROUND_ROBIN:return new d(e);case k.LESS_RECENTLY_USED:return new p(e);default:throw new Error(`Worker choice strategy '${r}' not found`)}}}class g extends u{constructor(e,r,t=k.ROUND_ROBIN){super(e),this.createDynamicallyWorkerCallback=r,this.workerChoiceStrategy=W.getWorkerChoiceStrategy(this.pool,t)}choose(){const e=this.pool.findFreeWorker();return e||(this.pool.busy?this.workerChoiceStrategy.choose():this.createDynamicallyWorkerCallback())}}class m{constructor(e,r,t=k.ROUND_ROBIN){this.pool=e,this.createDynamicallyWorkerCallback=r,this.setWorkerChoiceStrategy(t)}getPoolWorkerChoiceStrategy(e=k.ROUND_ROBIN){return this.pool.type===i.DYNAMIC?new g(this.pool,this.createDynamicallyWorkerCallback,e):W.getWorkerChoiceStrategy(this.pool,e)}setWorkerChoiceStrategy(e){this.workerChoiceStrategy=this.getPoolWorkerChoiceStrategy(e)}execute(){return this.workerChoiceStrategy.choose()}}class y{constructor(e,r,t){if(this.numberOfWorkers=e,this.filePath=r,this.opts=t,this.workers=[],this.tasks=new Map,this.promiseMap=new Map,this.nextMessageId=0,!this.isMain())throw new Error("Cannot start a pool from a worker!");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),this.checkPoolOptions(this.opts),this.setupHook();for(let e=1;e<=this.numberOfWorkers;e++)this.createAndSetupWorker();this.opts.enableEvents&&(this.emitter=new h),this.workerChoiceStrategyContext=new m(this,(()=>{const e=this.createAndSetupWorker();return this.registerWorkerMessageListener(e,(r=>{var t;t=l.HARD,(r.kill===t||0===this.getWorkerRunningTasks(e))&&this.destroyWorker(e)})),e}),this.opts.workerChoiceStrategy)}checkFilePath(e){if(!e)throw new Error("Please specify a file with a worker implementation")}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new Error("Cannot instantiate a pool with a non integer number of workers");if(e<0)throw new Error("Cannot instantiate a pool with a negative number of workers");if(this.type===i.FIXED&&0===e)throw new Error("Cannot instantiate a fixed pool with no worker")}checkPoolOptions(e){var r,t;this.opts.workerChoiceStrategy=null!==(r=e.workerChoiceStrategy)&&void 0!==r?r:k.ROUND_ROBIN,this.opts.enableEvents=null===(t=e.enableEvents)||void 0===t||t}get numberOfRunningTasks(){return this.promiseMap.size}getWorkerRunningTasks(e){return this.tasks.get(e)}getWorkerIndex(e){return this.workers.indexOf(e)}setWorkerChoiceStrategy(e){this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(e)}internalGetBusyStatus(){return this.numberOfRunningTasks>=this.numberOfWorkers&&!1===this.findFreeWorker()}findFreeWorker(){for(const e of this.workers)if(0===this.getWorkerRunningTasks(e))return e;return!1}execute(e){const r=this.chooseWorker(),t=++this.nextMessageId,s=this.internalExecute(r,t);return this.checkAndEmitBusy(),e=null!=e?e:{},this.sendToWorker(r,{data:e,id:t}),s}async destroy(){await Promise.all(this.workers.map((e=>this.destroyWorker(e))))}setupHook(){}increaseWorkersTask(e){this.stepWorkerNumberOfTasks(e,1)}decreaseWorkersTasks(e){this.stepWorkerNumberOfTasks(e,-1)}stepWorkerNumberOfTasks(e,r){const t=this.tasks.get(e);if(void 0===t)throw Error("Worker could not be found in tasks map");this.tasks.set(e,t+r)}removeWorker(e){this.workers.splice(this.getWorkerIndex(e),1),this.tasks.delete(e)}chooseWorker(){return this.workerChoiceStrategyContext.execute()}internalExecute(e,r){return this.increaseWorkersTask(e),new Promise(((t,s)=>{this.promiseMap.set(r,{resolve:t,reject:s,worker:e})}))}createAndSetupWorker(){var e,r,t,s;const o=this.createWorker();return o.on("message",null!==(e=this.opts.messageHandler)&&void 0!==e?e:c),o.on("error",null!==(r=this.opts.errorHandler)&&void 0!==r?r:c),o.on("online",null!==(t=this.opts.onlineHandler)&&void 0!==t?t:c),o.on("exit",null!==(s=this.opts.exitHandler)&&void 0!==s?s:c),o.once("exit",(()=>this.removeWorker(o))),this.workers.push(o),this.tasks.set(o,0),this.afterWorkerSetup(o),o}workerListener(){return e=>{if(void 0!==e.id){const r=this.promiseMap.get(e.id);void 0!==r&&(this.decreaseWorkersTasks(r.worker),e.error?r.reject(e.error):r.resolve(e.data),this.promiseMap.delete(e.id))}}}checkAndEmitBusy(){var e;this.opts.enableEvents&&this.busy&&(null===(e=this.emitter)||void 0===e||e.emit("busy"))}}class w extends y{constructor(e,r,t={}){super(e,r,t),this.opts=t}setupHook(){a.default.setupPrimary({exec:this.filePath})}isMain(){return a.default.isPrimary}destroyWorker(e){this.sendToWorker(e,{kill:1}),e.kill()}sendToWorker(e,r){e.send(r)}registerWorkerMessageListener(e,r){e.on("message",r)}createWorker(){return a.default.fork(this.opts.env)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,super.workerListener())}get type(){return i.FIXED}get busy(){return this.internalGetBusyStatus()}}class f extends y{constructor(e,r,t={}){super(e,r,t)}isMain(){return t.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:1}),await e.terminate()}sendToWorker(e,r){e.postMessage(r)}registerWorkerMessageListener(e,r){var t;null===(t=e.port2)||void 0===t||t.on("message",r)}createWorker(){return new t.Worker(this.filePath,{env:t.SHARE_ENV})}afterWorkerSetup(e){const{port1:r,port2:s}=new t.MessageChannel;e.postMessage({parent:r},[r]),e.port1=r,e.port2=s,this.registerWorkerMessageListener(e,super.workerListener())}get type(){return i.FIXED}get busy(){return this.internalGetBusyStatus()}}const v=l.SOFT;class x extends s.AsyncResource{constructor(e,r,t,s,o={killBehavior:v,maxInactiveTime:6e4}){var i,n;super(e),this.mainWorker=s,this.opts=o,this.checkFunctionInput(t),this.checkWorkerOptions(this.opts),this.lastTaskTimestamp=Date.now(),r||(this.aliveInterval=setInterval(this.checkAlive.bind(this),(null!==(i=this.opts.maxInactiveTime)&&void 0!==i?i:6e4)/2),this.checkAlive.bind(this)()),null===(n=this.mainWorker)||void 0===n||n.on("message",(e=>{this.messageListener(e,t)}))}messageListener(e,r){void 0!==e.data&&void 0!==e.id?this.opts.async?this.runInAsyncScope(this.runAsync.bind(this),this,r,e):this.runInAsyncScope(this.run.bind(this),this,r,e):void 0!==e.parent?this.mainWorker=e.parent:void 0!==e.kill&&(this.aliveInterval&&clearInterval(this.aliveInterval),this.emitDestroy())}checkWorkerOptions(e){var r,t;this.opts.killBehavior=null!==(r=e.killBehavior)&&void 0!==r?r:v,this.opts.maxInactiveTime=null!==(t=e.maxInactiveTime)&&void 0!==t?t:6e4,this.opts.async=!!e.async}checkFunctionInput(e){if(!e)throw new Error("fn parameter is mandatory")}getMainWorker(){if(!this.mainWorker)throw new Error("Main worker was not set");return this.mainWorker}checkAlive(){var e;Date.now()-this.lastTaskTimestamp>(null!==(e=this.opts.maxInactiveTime)&&void 0!==e?e:6e4)&&this.sendToMainWorker({kill:this.opts.killBehavior})}handleError(e){return e}run(e,r){try{const t=e(r.data);this.sendToMainWorker({data:t,id:r.id})}catch(e){const t=this.handleError(e);this.sendToMainWorker({error:t,id:r.id})}finally{this.lastTaskTimestamp=Date.now()}}runAsync(e,r){e(r.data).then((e=>(this.sendToMainWorker({data:e,id:r.id}),null))).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({error:t,id:r.id})})).finally((()=>{this.lastTaskTimestamp=Date.now()})).catch(c)}}exports.AbstractWorker=x,exports.ClusterWorker=class extends x{constructor(e,r={}){super("worker-cluster-pool:poolifier",a.default.isPrimary,e,a.default.worker,r)}sendToMainWorker(e){this.getMainWorker().send(e)}handleError(e){return e instanceof Error?e.message:e}},exports.DynamicClusterPool=class extends w{constructor(e,r,t,s={}){super(e,t,s),this.max=r}get type(){return i.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.DynamicThreadPool=class extends f{constructor(e,r,t,s={}){super(e,t,s),this.max=r}get type(){return i.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.FixedClusterPool=w,exports.FixedThreadPool=f,exports.KillBehaviors=l,exports.ThreadWorker=class extends x{constructor(e,r={}){super("worker-thread-pool:poolifier",t.isMainThread,e,t.parentPort,r)}sendToMainWorker(e){this.getMainWorker().postMessage(e)}},exports.WorkerChoiceStrategies=k;
1
+ "use strict";var e,r=require("events"),t=require("cluster"),s=require("os"),o=require("worker_threads"),i=require("async_hooks");!function(e){e.FIXED="fixed",e.DYNAMIC="dynamic"}(e||(e={}));class n extends r{}const a=()=>{},h=Object.freeze({SOFT:"SOFT",HARD:"HARD"});const k=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LESS_RECENTLY_USED:"LESS_RECENTLY_USED",FAIR_SHARE:"FAIR_SHARE",WEIGHTED_ROUND_ROBIN:"WEIGHTED_ROUND_ROBIN"});class u{constructor(r){this.pool=r,this.isDynamicPool=this.pool.type===e.DYNAMIC,this.requiredStatistics={runTime:!1}}}class c extends u{constructor(){super(...arguments),this.requiredStatistics={runTime:!0},this.workerLastVirtualTaskTimestamp=new Map}reset(){return this.workerLastVirtualTaskTimestamp.clear(),!0}choose(){this.computeWorkerLastVirtualTaskTimestamp();let e,r=1/0;for(const t of this.pool.workers){const s=this.workerLastVirtualTaskTimestamp.get(t)?.end??0;s<r&&(r=s,e=t)}return e}computeWorkerLastVirtualTaskTimestamp(){for(const e of this.pool.workers){const r=Math.max(Date.now(),this.workerLastVirtualTaskTimestamp.get(e)?.end??-1/0),t=r+(this.pool.getWorkerAverageTasksRunTime(e)??0);this.workerLastVirtualTaskTimestamp.set(e,{start:r,end:t})}}}class l extends u{reset(){return!0}choose(){let e,r=1/0;for(const t of this.pool.workers){const s=this.pool.getWorkerRunningTasks(t);if(!1===this.isDynamicPool&&0===s)return t;s<r&&(e=t,r=s)}return e}}class p extends u{constructor(){super(...arguments),this.nextWorkerIndex=0}reset(){return this.nextWorkerIndex=0,!0}choose(){const e=this.pool.workers[this.nextWorkerIndex];return this.nextWorkerIndex=this.nextWorkerIndex===this.pool.workers.length-1?0:this.nextWorkerIndex+1,e}}class W extends u{constructor(e){super(e),this.requiredStatistics={runTime:!0},this.previousWorkerIndex=0,this.currentWorkerIndex=0,this.workersTaskRunTime=new Map,this.defaultWorkerWeight=this.computeWorkerWeight(),this.initWorkersTaskRunTime()}reset(){return this.previousWorkerIndex=0,this.currentWorkerIndex=0,this.workersTaskRunTime.clear(),this.initWorkersTaskRunTime(),!0}choose(){const e=this.pool.workers[this.currentWorkerIndex];!0===this.isDynamicPool&&!1===this.workersTaskRunTime.has(e)&&this.initWorkerTaskRunTime(e);const r=this.getWorkerVirtualTaskRunTime(e)??0,t=this.workersTaskRunTime.get(e)?.weight??this.defaultWorkerWeight;if(this.currentWorkerIndex===this.previousWorkerIndex){const s=(this.workersTaskRunTime.get(e)?.runTime??0)+r;this.setWorkerTaskRunTime(e,t,s)}else this.setWorkerTaskRunTime(e,t,0);return r<t?this.previousWorkerIndex=this.currentWorkerIndex:(this.previousWorkerIndex=this.currentWorkerIndex,this.currentWorkerIndex=this.pool.workers.length-1===this.currentWorkerIndex?0:this.currentWorkerIndex+1),this.pool.workers[this.currentWorkerIndex]}initWorkersTaskRunTime(){for(const e of this.pool.workers)this.initWorkerTaskRunTime(e)}initWorkerTaskRunTime(e){this.setWorkerTaskRunTime(e,this.defaultWorkerWeight,0)}setWorkerTaskRunTime(e,r,t){this.workersTaskRunTime.set(e,{weight:r,runTime:t})}getWorkerVirtualTaskRunTime(e){return this.pool.getWorkerAverageTasksRunTime(e)}computeWorkerWeight(){let e=0;for(const r of s.cpus()){const t=r.speed.toString().length-1;e+=1/(r.speed/Math.pow(10,t))*Math.pow(10,t)}return Math.round(e/s.cpus().length)}}class g{static getWorkerChoiceStrategy(e,r=k.ROUND_ROBIN){switch(r){case k.ROUND_ROBIN:return new p(e);case k.LESS_RECENTLY_USED:return new l(e);case k.FAIR_SHARE:return new c(e);case k.WEIGHTED_ROUND_ROBIN:return new W(e);default:throw new Error(`Worker choice strategy '${r}' not found`)}}}class d extends u{constructor(e,r,t=k.ROUND_ROBIN){super(e),this.createDynamicallyWorkerCallback=r,this.workerChoiceStrategy=g.getWorkerChoiceStrategy(this.pool,t),this.requiredStatistics=this.workerChoiceStrategy.requiredStatistics}reset(){return this.workerChoiceStrategy.reset()}choose(){const e=this.pool.findFreeWorker();return e||(!0===this.pool.busy?this.workerChoiceStrategy.choose():this.createDynamicallyWorkerCallback())}}class m{constructor(e,r,t=k.ROUND_ROBIN){this.pool=e,this.createDynamicallyWorkerCallback=r,this.setWorkerChoiceStrategy(t)}getPoolWorkerChoiceStrategy(r=k.ROUND_ROBIN){return this.pool.type===e.DYNAMIC?new d(this.pool,this.createDynamicallyWorkerCallback,r):g.getWorkerChoiceStrategy(this.pool,r)}getWorkerChoiceStrategy(){return this.workerChoiceStrategy}setWorkerChoiceStrategy(e){this.workerChoiceStrategy?.reset(),this.workerChoiceStrategy=this.getPoolWorkerChoiceStrategy(e)}execute(){return this.workerChoiceStrategy.choose()}}class T{constructor(e,r,t){if(this.numberOfWorkers=e,this.filePath=r,this.opts=t,this.workers=[],this.workersTasksUsage=new Map,this.promiseMap=new Map,this.nextMessageId=0,!this.isMain())throw new Error("Cannot start a pool from a worker!");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),this.checkPoolOptions(this.opts),this.setupHook();for(let e=1;e<=this.numberOfWorkers;e++)this.createAndSetupWorker();this.opts.enableEvents&&(this.emitter=new n),this.workerChoiceStrategyContext=new m(this,(()=>{const e=this.createAndSetupWorker();return this.registerWorkerMessageListener(e,(r=>{var t;t=h.HARD,(r.kill===t||0===this.getWorkerRunningTasks(e))&&this.destroyWorker(e)})),e}),this.opts.workerChoiceStrategy)}checkFilePath(e){if(!e)throw new Error("Please specify a file with a worker implementation")}checkNumberOfWorkers(r){if(null==r)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!1===Number.isSafeInteger(r))throw new Error("Cannot instantiate a pool with a non integer number of workers");if(r<0)throw new Error("Cannot instantiate a pool with a negative number of workers");if(this.type===e.FIXED&&0===r)throw new Error("Cannot instantiate a fixed pool with no worker")}checkPoolOptions(e){this.opts.workerChoiceStrategy=e.workerChoiceStrategy??k.ROUND_ROBIN,this.opts.enableEvents=e.enableEvents??!0}get numberOfRunningTasks(){return this.promiseMap.size}getWorkerIndex(e){return this.workers.indexOf(e)}getWorkerRunningTasks(e){return this.workersTasksUsage.get(e)?.running}getWorkerAverageTasksRunTime(e){return this.workersTasksUsage.get(e)?.avgRunTime}setWorkerChoiceStrategy(e){this.opts.workerChoiceStrategy=e;for(const e of this.workers)this.resetWorkerTasksUsage(e);this.workerChoiceStrategyContext.setWorkerChoiceStrategy(e)}internalGetBusyStatus(){return this.numberOfRunningTasks>=this.numberOfWorkers&&!1===this.findFreeWorker()}findFreeWorker(){for(const e of this.workers)if(0===this.getWorkerRunningTasks(e))return e;return!1}execute(e){const r=this.chooseWorker(),t=++this.nextMessageId,s=this.internalExecute(r,t);return this.checkAndEmitBusy(),e=e??{},this.sendToWorker(r,{data:e,id:t}),s}async destroy(){await Promise.all(this.workers.map((e=>this.destroyWorker(e))))}setupHook(){}beforePromiseWorkerResponseHook(e){this.increaseWorkerRunningTasks(e)}afterPromiseWorkerResponseHook(e,r){this.decreaseWorkerRunningTasks(r.worker),this.stepWorkerRunTasks(r.worker,1),this.updateWorkerTasksRunTime(r.worker,e.taskRunTime)}removeWorker(e){this.workers.splice(this.getWorkerIndex(e),1),this.removeWorkerTasksUsage(e)}chooseWorker(){return this.workerChoiceStrategyContext.execute()}internalExecute(e,r){return this.beforePromiseWorkerResponseHook(e),new Promise(((t,s)=>{this.promiseMap.set(r,{resolve:t,reject:s,worker:e})}))}createAndSetupWorker(){const e=this.createWorker();return e.on("message",this.opts.messageHandler??a),e.on("error",this.opts.errorHandler??a),e.on("online",this.opts.onlineHandler??a),e.on("exit",this.opts.exitHandler??a),e.once("exit",(()=>this.removeWorker(e))),this.workers.push(e),this.initWorkerTasksUsage(e),this.afterWorkerSetup(e),e}workerListener(){return e=>{if(void 0!==e.id){const r=this.promiseMap.get(e.id);void 0!==r&&(this.afterPromiseWorkerResponseHook(e,r),e.error?r.reject(e.error):r.resolve(e.data),this.promiseMap.delete(e.id))}}}checkAndEmitBusy(){this.opts.enableEvents&&this.busy&&this.emitter?.emit("busy")}increaseWorkerRunningTasks(e){this.stepWorkerRunningTasks(e,1)}decreaseWorkerRunningTasks(e){this.stepWorkerRunningTasks(e,-1)}stepWorkerRunningTasks(e,r){const t=this.workersTasksUsage.get(e);if(void 0===t)throw new Error("Worker could not be found in worker tasks usage map");t.running=t.running+r,this.workersTasksUsage.set(e,t)}stepWorkerRunTasks(e,r){const t=this.workersTasksUsage.get(e);if(void 0===t)throw new Error("Worker could not be found in worker tasks usage map");t.run=t.run+r,this.workersTasksUsage.set(e,t)}updateWorkerTasksRunTime(e,r){if(!0===this.workerChoiceStrategyContext.getWorkerChoiceStrategy().requiredStatistics.runTime){const t=this.workersTasksUsage.get(e);if(void 0===t)throw new Error("Worker could not be found in worker tasks usage map");t.runTime+=r??0,0!==t.run&&(t.avgRunTime=t.runTime/t.run),this.workersTasksUsage.set(e,t)}}initWorkerTasksUsage(e){this.workersTasksUsage.set(e,{run:0,running:0,runTime:0,avgRunTime:0})}removeWorkerTasksUsage(e){this.workersTasksUsage.delete(e)}resetWorkerTasksUsage(e){this.removeWorkerTasksUsage(e),this.initWorkerTasksUsage(e)}}class w extends T{constructor(e,r,t={}){super(e,r,t),this.opts=t}setupHook(){t.setupPrimary({exec:this.filePath})}isMain(){return t.isPrimary}destroyWorker(e){this.sendToWorker(e,{kill:1}),e.kill()}sendToWorker(e,r){e.send(r)}registerWorkerMessageListener(e,r){e.on("message",r)}createWorker(){return t.fork(this.opts.env)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,super.workerListener())}get type(){return e.FIXED}get busy(){return this.internalGetBusyStatus()}}class y extends T{constructor(e,r,t={}){super(e,r,t)}isMain(){return o.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:1}),await e.terminate()}sendToWorker(e,r){e.postMessage(r)}registerWorkerMessageListener(e,r){e.port2?.on("message",r)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV})}afterWorkerSetup(e){const{port1:r,port2:t}=new o.MessageChannel;e.postMessage({parent:r},[r]),e.port1=r,e.port2=t,this.registerWorkerMessageListener(e,super.workerListener())}get type(){return e.FIXED}get busy(){return this.internalGetBusyStatus()}}const R=h.SOFT;class f extends i.AsyncResource{constructor(e,r,t,s,o={killBehavior:R,maxInactiveTime:6e4}){super(e),this.mainWorker=s,this.opts=o,this.checkFunctionInput(t),this.checkWorkerOptions(this.opts),this.lastTaskTimestamp=Date.now(),!1===r&&(this.aliveInterval=setInterval(this.checkAlive.bind(this),(this.opts.maxInactiveTime??6e4)/2),this.checkAlive.bind(this)()),this.mainWorker?.on("message",(e=>{this.messageListener(e,t)}))}messageListener(e,r){void 0!==e.data&&void 0!==e.id?this.opts.async?this.runInAsyncScope(this.runAsync.bind(this),this,r,e):this.runInAsyncScope(this.run.bind(this),this,r,e):void 0!==e.parent?this.mainWorker=e.parent:void 0!==e.kill&&(this.aliveInterval&&clearInterval(this.aliveInterval),this.emitDestroy())}checkWorkerOptions(e){this.opts.killBehavior=e.killBehavior??R,this.opts.maxInactiveTime=e.maxInactiveTime??6e4,this.opts.async=!!e.async}checkFunctionInput(e){if(!e)throw new Error("fn parameter is mandatory")}getMainWorker(){if(!this.mainWorker)throw new Error("Main worker was not set");return this.mainWorker}checkAlive(){Date.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??6e4)&&this.sendToMainWorker({kill:this.opts.killBehavior})}handleError(e){return e}run(e,r){try{const t=Date.now(),s=e(r.data),o=Date.now()-t;this.sendToMainWorker({data:s,id:r.id,taskRunTime:o})}catch(e){const t=this.handleError(e);this.sendToMainWorker({error:t,id:r.id})}finally{this.lastTaskTimestamp=Date.now()}}runAsync(e,r){const t=Date.now();e(r.data).then((e=>{const s=Date.now()-t;return this.sendToMainWorker({data:e,id:r.id,taskRunTime:s}),null})).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({error:t,id:r.id})})).finally((()=>{this.lastTaskTimestamp=Date.now()})).catch(a)}}exports.AbstractWorker=f,exports.ClusterWorker=class extends f{constructor(e,r={}){super("worker-cluster-pool:poolifier",t.isPrimary,e,t.worker,r)}sendToMainWorker(e){this.getMainWorker().send(e)}handleError(e){return e instanceof Error?e.message:e}},exports.DynamicClusterPool=class extends w{constructor(e,r,t,s={}){super(e,t,s),this.max=r}get type(){return e.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.DynamicThreadPool=class extends y{constructor(e,r,t,s={}){super(e,t,s),this.max=r}get type(){return e.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.FixedClusterPool=w,exports.FixedThreadPool=y,exports.KillBehaviors=h,exports.ThreadWorker=class extends f{constructor(e,r={}){super("worker-thread-pool:poolifier",o.isMainThread,e,o.parentPort,r)}sendToMainWorker(e){this.getMainWorker().postMessage(e)}},exports.WorkerChoiceStrategies=k;
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "poolifier",
3
- "version": "2.2.2",
3
+ "version": "2.3.0",
4
4
  "description": "A fast, easy to use Node.js Worker Thread Pool and Cluster Pool implementation",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
7
+ "prepare": "node prepare.js",
7
8
  "build": "rollup --config --environment BUILD:development",
8
9
  "build:typedoc": "rollup --config --environment BUILD:development --environment DOCUMENTATION",
9
10
  "build:prod": "rollup --config",
@@ -17,6 +18,7 @@
17
18
  "format": "prettier --loglevel silent --write .; prettierx --write .",
18
19
  "lint": "eslint . --cache",
19
20
  "lint:fix": "eslint . --cache --fix",
21
+ "lint:report": "eslint . --cache --format json --output-file reports/eslint.json",
20
22
  "typedoc": "typedoc",
21
23
  "sonar:properties": "./updateSonarProps.sh",
22
24
  "prepublishOnly": "npm run build:prod"
@@ -62,9 +64,9 @@
62
64
  "lib"
63
65
  ],
64
66
  "devDependencies": {
65
- "@types/node": "^18.8.3",
66
- "@typescript-eslint/eslint-plugin": "^5.39.0",
67
- "@typescript-eslint/parser": "^5.39.0",
67
+ "@types/node": "^18.8.4",
68
+ "@typescript-eslint/eslint-plugin": "^5.40.0",
69
+ "@typescript-eslint/parser": "^5.40.0",
68
70
  "benchmark": "^2.1.4",
69
71
  "eslint": "^8.25.0",
70
72
  "eslint-config-standard": "^17.0.0",
@@ -75,9 +77,11 @@
75
77
  "eslint-plugin-n": "^15.3.0",
76
78
  "eslint-plugin-node": "^11.1.0",
77
79
  "eslint-plugin-prettierx": "^0.18.0",
78
- "eslint-plugin-promise": "^6.0.1",
80
+ "eslint-plugin-promise": "^6.1.0",
79
81
  "eslint-plugin-spellcheck": "^0.0.19",
80
82
  "expect": "^29.1.2",
83
+ "husky": "^8.0.1",
84
+ "lint-staged": "^13.0.3",
81
85
  "microtime": "^3.1.1",
82
86
  "mocha": "^10.0.0",
83
87
  "mochawesome": "^7.1.3",
@@ -85,7 +89,7 @@
85
89
  "prettier": "^2.7.1",
86
90
  "prettier-plugin-organize-imports": "^3.1.1",
87
91
  "prettierx": "^0.18.3",
88
- "rollup": "^2.79.1",
92
+ "rollup": "^3.1.0",
89
93
  "rollup-plugin-analyzer": "^4.0.0",
90
94
  "rollup-plugin-command": "^1.1.3",
91
95
  "rollup-plugin-delete": "^2.0.0",
@@ -94,7 +98,7 @@
94
98
  "rollup-plugin-ts": "^3.0.2",
95
99
  "sinon": "^14.0.1",
96
100
  "source-map-support": "^0.5.21",
97
- "typedoc": "^0.23.15",
101
+ "typedoc": "^0.23.16",
98
102
  "typescript": "^4.8.4"
99
103
  },
100
104
  "engines": {