poolifier 3.1.6 → 3.1.8
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/lib/index.d.ts +36 -34
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1 -1
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -2
package/lib/index.d.ts
CHANGED
|
@@ -712,12 +712,6 @@ interface MeasurementOptions {
|
|
|
712
712
|
* Worker choice strategy options.
|
|
713
713
|
*/
|
|
714
714
|
interface WorkerChoiceStrategyOptions {
|
|
715
|
-
/**
|
|
716
|
-
* Number of worker choice retries to perform if no worker is eligible.
|
|
717
|
-
*
|
|
718
|
-
* @defaultValue 6
|
|
719
|
-
*/
|
|
720
|
-
readonly retries?: number;
|
|
721
715
|
/**
|
|
722
716
|
* Measurement to use in worker choice strategy supporting it.
|
|
723
717
|
*/
|
|
@@ -746,7 +740,20 @@ interface WorkerChoiceStrategyOptions {
|
|
|
746
740
|
*
|
|
747
741
|
* @defaultValue Weights computed automatically given the CPU performance.
|
|
748
742
|
*/
|
|
749
|
-
|
|
743
|
+
weights?: Record<number, number>;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Worker choice strategy internal options.
|
|
747
|
+
*
|
|
748
|
+
* @internal
|
|
749
|
+
*/
|
|
750
|
+
interface InternalWorkerChoiceStrategyOptions extends WorkerChoiceStrategyOptions {
|
|
751
|
+
/**
|
|
752
|
+
* Number of worker choice retries to perform if no worker is eligible.
|
|
753
|
+
*
|
|
754
|
+
* @defaultValue pool maximum size
|
|
755
|
+
*/
|
|
756
|
+
readonly retries?: number;
|
|
750
757
|
}
|
|
751
758
|
/**
|
|
752
759
|
* Measurement statistics requirements.
|
|
@@ -1183,7 +1190,7 @@ interface IPool<Worker extends IWorker, Data = unknown, Response = unknown> {
|
|
|
1183
1190
|
*/
|
|
1184
1191
|
declare class WorkerChoiceStrategyContext<Worker extends IWorker, Data = unknown, Response = unknown> {
|
|
1185
1192
|
private workerChoiceStrategy;
|
|
1186
|
-
private opts
|
|
1193
|
+
private opts?;
|
|
1187
1194
|
private readonly workerChoiceStrategies;
|
|
1188
1195
|
/**
|
|
1189
1196
|
* Worker choice strategy context constructor.
|
|
@@ -1192,7 +1199,7 @@ declare class WorkerChoiceStrategyContext<Worker extends IWorker, Data = unknown
|
|
|
1192
1199
|
* @param workerChoiceStrategy - The worker choice strategy.
|
|
1193
1200
|
* @param opts - The worker choice strategy options.
|
|
1194
1201
|
*/
|
|
1195
|
-
constructor(pool: IPool<Worker, Data, Response>, workerChoiceStrategy?: WorkerChoiceStrategy, opts?:
|
|
1202
|
+
constructor(pool: IPool<Worker, Data, Response>, workerChoiceStrategy?: WorkerChoiceStrategy, opts?: InternalWorkerChoiceStrategyOptions | undefined);
|
|
1196
1203
|
/**
|
|
1197
1204
|
* Gets the strategy policy in the context.
|
|
1198
1205
|
*
|
|
@@ -1222,9 +1229,16 @@ declare class WorkerChoiceStrategyContext<Worker extends IWorker, Data = unknown
|
|
|
1222
1229
|
*
|
|
1223
1230
|
* @returns The key of the worker node.
|
|
1224
1231
|
* @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
|
|
1225
|
-
* @throws {@link https://nodejs.org/api/errors.html#class-rangeerror} If the maximum consecutive worker choice strategy executions has been reached.
|
|
1226
1232
|
*/
|
|
1227
1233
|
execute(): number;
|
|
1234
|
+
/**
|
|
1235
|
+
* Executes the given worker choice strategy.
|
|
1236
|
+
*
|
|
1237
|
+
* @param workerChoiceStrategy - The worker choice strategy.
|
|
1238
|
+
* @returns The key of the worker node.
|
|
1239
|
+
* @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined.
|
|
1240
|
+
*/
|
|
1241
|
+
private executeStrategy;
|
|
1228
1242
|
/**
|
|
1229
1243
|
* Removes the worker node key from the worker choice strategy in the context.
|
|
1230
1244
|
*
|
|
@@ -1235,9 +1249,10 @@ declare class WorkerChoiceStrategyContext<Worker extends IWorker, Data = unknown
|
|
|
1235
1249
|
/**
|
|
1236
1250
|
* Sets the worker choice strategies in the context options.
|
|
1237
1251
|
*
|
|
1252
|
+
* @param pool - The pool instance.
|
|
1238
1253
|
* @param opts - The worker choice strategy options.
|
|
1239
1254
|
*/
|
|
1240
|
-
setOptions(
|
|
1255
|
+
setOptions(pool: IPool<Worker, Data, Response>, opts?: InternalWorkerChoiceStrategyOptions): void;
|
|
1241
1256
|
}
|
|
1242
1257
|
|
|
1243
1258
|
/**
|
|
@@ -1248,17 +1263,14 @@ declare class WorkerChoiceStrategyContext<Worker extends IWorker, Data = unknown
|
|
|
1248
1263
|
* @typeParam Response - Type of execution response. This can only be structured-cloneable data.
|
|
1249
1264
|
*/
|
|
1250
1265
|
declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Response = unknown> implements IPool<Worker, Data, Response> {
|
|
1251
|
-
protected readonly
|
|
1266
|
+
protected readonly minimumNumberOfWorkers: number;
|
|
1252
1267
|
protected readonly filePath: string;
|
|
1253
1268
|
protected readonly opts: PoolOptions<Worker>;
|
|
1269
|
+
protected readonly maximumNumberOfWorkers?: number | undefined;
|
|
1254
1270
|
/** @inheritDoc */
|
|
1255
1271
|
readonly workerNodes: Array<IWorkerNode<Worker, Data>>;
|
|
1256
1272
|
/** @inheritDoc */
|
|
1257
1273
|
emitter?: EventEmitterAsyncResource;
|
|
1258
|
-
/**
|
|
1259
|
-
* Dynamic pool maximum size property placeholder.
|
|
1260
|
-
*/
|
|
1261
|
-
protected readonly max?: number;
|
|
1262
1274
|
/**
|
|
1263
1275
|
* The task execution response promise map:
|
|
1264
1276
|
* - `key`: The message id of each submitted task.
|
|
@@ -1300,12 +1312,14 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
|
|
|
1300
1312
|
/**
|
|
1301
1313
|
* Constructs a new poolifier pool.
|
|
1302
1314
|
*
|
|
1303
|
-
* @param
|
|
1315
|
+
* @param minimumNumberOfWorkers - Minimum number of workers that this pool manages.
|
|
1304
1316
|
* @param filePath - Path to the worker file.
|
|
1305
1317
|
* @param opts - Options for the pool.
|
|
1318
|
+
* @param maximumNumberOfWorkers - Maximum number of workers that this pool manages.
|
|
1306
1319
|
*/
|
|
1307
|
-
constructor(
|
|
1308
|
-
private
|
|
1320
|
+
constructor(minimumNumberOfWorkers: number, filePath: string, opts: PoolOptions<Worker>, maximumNumberOfWorkers?: number | undefined);
|
|
1321
|
+
private checkPoolType;
|
|
1322
|
+
private checkMinimumNumberOfWorkers;
|
|
1309
1323
|
private checkPoolOptions;
|
|
1310
1324
|
private checkValidWorkerChoiceStrategyOptions;
|
|
1311
1325
|
private initializeEventEmitter;
|
|
@@ -1331,14 +1345,6 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
|
|
|
1331
1345
|
* The worker type.
|
|
1332
1346
|
*/
|
|
1333
1347
|
protected abstract get worker(): WorkerType;
|
|
1334
|
-
/**
|
|
1335
|
-
* The pool minimum size.
|
|
1336
|
-
*/
|
|
1337
|
-
protected get minSize(): number;
|
|
1338
|
-
/**
|
|
1339
|
-
* The pool maximum size.
|
|
1340
|
-
*/
|
|
1341
|
-
protected get maxSize(): number;
|
|
1342
1348
|
/**
|
|
1343
1349
|
* Checks if the worker id sent in the received message from a worker is valid.
|
|
1344
1350
|
*
|
|
@@ -1406,7 +1412,7 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
|
|
|
1406
1412
|
start(): void;
|
|
1407
1413
|
/** @inheritDoc */
|
|
1408
1414
|
destroy(): Promise<void>;
|
|
1409
|
-
|
|
1415
|
+
private sendKillMessageToWorker;
|
|
1410
1416
|
/**
|
|
1411
1417
|
* Terminates the worker node given its worker node key.
|
|
1412
1418
|
*
|
|
@@ -1594,7 +1600,6 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
|
|
|
1594
1600
|
* @since 2.0.0
|
|
1595
1601
|
*/
|
|
1596
1602
|
declare class FixedClusterPool<Data = unknown, Response = unknown> extends AbstractPool<Worker, Data, Response> {
|
|
1597
|
-
protected readonly opts: PoolOptions<Worker>;
|
|
1598
1603
|
/**
|
|
1599
1604
|
* Constructs a new poolifier fixed cluster pool.
|
|
1600
1605
|
*
|
|
@@ -1602,7 +1607,7 @@ declare class FixedClusterPool<Data = unknown, Response = unknown> extends Abstr
|
|
|
1602
1607
|
* @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute.
|
|
1603
1608
|
* @param opts - Options for this fixed cluster pool.
|
|
1604
1609
|
*/
|
|
1605
|
-
constructor(numberOfWorkers: number, filePath: string, opts?: PoolOptions<Worker
|
|
1610
|
+
constructor(numberOfWorkers: number, filePath: string, opts?: PoolOptions<Worker>, maximumNumberOfWorkers?: number);
|
|
1606
1611
|
/** @inheritDoc */
|
|
1607
1612
|
protected setupHook(): void;
|
|
1608
1613
|
/** @inheritDoc */
|
|
@@ -1637,7 +1642,6 @@ declare class FixedClusterPool<Data = unknown, Response = unknown> extends Abstr
|
|
|
1637
1642
|
* @since 2.0.0
|
|
1638
1643
|
*/
|
|
1639
1644
|
declare class DynamicClusterPool<Data = unknown, Response = unknown> extends FixedClusterPool<Data, Response> {
|
|
1640
|
-
protected readonly max: number;
|
|
1641
1645
|
/**
|
|
1642
1646
|
* Constructs a new poolifier dynamic cluster pool.
|
|
1643
1647
|
*
|
|
@@ -1662,7 +1666,6 @@ declare class DynamicClusterPool<Data = unknown, Response = unknown> extends Fix
|
|
|
1662
1666
|
* @since 0.0.1
|
|
1663
1667
|
*/
|
|
1664
1668
|
declare class FixedThreadPool<Data = unknown, Response = unknown> extends AbstractPool<Worker$1, Data, Response> {
|
|
1665
|
-
protected readonly opts: PoolOptions<Worker$1>;
|
|
1666
1669
|
/**
|
|
1667
1670
|
* Constructs a new poolifier fixed thread pool.
|
|
1668
1671
|
*
|
|
@@ -1670,7 +1673,7 @@ declare class FixedThreadPool<Data = unknown, Response = unknown> extends Abstra
|
|
|
1670
1673
|
* @param filePath - Path to an implementation of a `ThreadWorker` file, which can be relative or absolute.
|
|
1671
1674
|
* @param opts - Options for this fixed thread pool.
|
|
1672
1675
|
*/
|
|
1673
|
-
constructor(numberOfThreads: number, filePath: string, opts?: PoolOptions<Worker$1
|
|
1676
|
+
constructor(numberOfThreads: number, filePath: string, opts?: PoolOptions<Worker$1>, maximumNumberOfThreads?: number);
|
|
1674
1677
|
/** @inheritDoc */
|
|
1675
1678
|
protected isMain(): boolean;
|
|
1676
1679
|
/** @inheritDoc */
|
|
@@ -1703,7 +1706,6 @@ declare class FixedThreadPool<Data = unknown, Response = unknown> extends Abstra
|
|
|
1703
1706
|
* @since 0.0.1
|
|
1704
1707
|
*/
|
|
1705
1708
|
declare class DynamicThreadPool<Data = unknown, Response = unknown> extends FixedThreadPool<Data, Response> {
|
|
1706
|
-
protected readonly max: number;
|
|
1707
1709
|
/**
|
|
1708
1710
|
* Constructs a new poolifier dynamic thread pool.
|
|
1709
1711
|
*
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("node:cluster"),t=require("node:fs"),s=require("node:worker_threads"),r=require("node:process"),i=require("node:os"),o=require("node:crypto"),n=require("node:perf_hooks"),a=require("node:events"),u=require("node:async_hooks");function h(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var k=h(i);const d=Object.freeze({fixed:"fixed",dynamic:"dynamic"}),c=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),l=Object.freeze({thread:"thread",cluster:"cluster"}),g="default",m=Object.freeze((()=>{})),w={retries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},p={aggregate:!1,average:!1,median:!1},y=t=>t instanceof s.Worker?l.thread:t instanceof e.Worker?l.cluster:void 0,T=t=>t instanceof s.Worker?t.threadId:t instanceof e.Worker?t.id:void 0,f=e=>Array.isArray(e)&&0===e.length?0:Array.isArray(e)&&1===e.length?e[0]:e.reduce(((e,t)=>e+t),0)/e.length,N=e=>{if(Array.isArray(e)&&0===e.length)return 0;if(Array.isArray(e)&&1===e.length)return e[0];const t=e.slice().sort(((e,t)=>e-t));return(t[t.length-1>>1]+t[t.length>>1])/2},W=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},S=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),v=(e,t)=>t===e,x=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,E=()=>o.getRandomValues(new Uint32Array(1))[0]/4294967296,I=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),F=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),b=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LEAST_USED:"LEAST_USED",LEAST_BUSY:"LEAST_BUSY",LEAST_ELU:"LEAST_ELU",FAIR_SHARE:"FAIR_SHARE",WEIGHTED_ROUND_ROBIN:"WEIGHTED_ROUND_ROBIN",INTERLEAVED_WEIGHTED_ROUND_ROBIN:"INTERLEAVED_WEIGHTED_ROUND_ROBIN"}),O=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),C=e=>({size:Math.pow(e,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,tasksFinishedTimeout:2e3}),R=e=>{if(null==e)throw new TypeError("The worker file path must be specified");if("string"!=typeof e)throw new TypeError("The worker file path must be a string");if(!t.existsSync(e))throw new Error(`Cannot find the worker file '${e}'`)},z=(e,t)=>{if(null==t)throw new TypeError("Cannot instantiate a dynamic pool without specifying the maximum pool size");if(!Number.isSafeInteger(t))throw new TypeError("Cannot instantiate a dynamic pool with a non safe integer maximum pool size");if(e>t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size");if(0===t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size equal to zero");if(e===t)throw new RangeError("Cannot instantiate a dynamic pool with a minimum pool size equal to the maximum pool size. Use a fixed pool instead")},P=e=>{if(null!=e&&!Object.values(b).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},M=e=>{if(null!=e&&!S(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker node tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new RangeError(`Invalid worker node tasks concurrency: ${e.concurrency} is a negative integer or zero`);if(null!=e?.size&&!Number.isSafeInteger(e.size))throw new TypeError("Invalid worker node tasks queue size: must be an integer");if(null!=e?.size&&e.size<=0)throw new RangeError(`Invalid worker node tasks queue size: ${e.size} is a negative integer or zero`)},q=(e,t,s)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=I(s,e.minimum??1/0),e.maximum=F(s,e.maximum??-1/0),(t.average||t.median)&&null!=s&&(e.history.push(s),t.average?e.average=f(e.history):null!=e.average&&delete e.average,t.median?e.median=N(e.history):null!=e.median&&delete e.median))};"test"===r.env.NODE_ENV&&(exports.updateMeasurementStatistics=q);const K=(e,t,s)=>{const r=performance.now(),i=r-(s.timestamp??r);q(t.waitTime,e.getTaskStatisticsRequirements().waitTime,i)},Q=(e,t)=>{const s=e.tasks;null!=s.executing&&s.executing>0&&--s.executing,null==t.workerError?++s.executed:++s.failed},U=(e,t,s)=>{null==s.workerError&&q(t.runTime,e.getTaskStatisticsRequirements().runTime,s.taskPerformance?.runTime??0)},A=(e,t,s)=>{if(null!=s.workerError)return;const r=e.getTaskStatisticsRequirements().elu;q(t.elu.active,r,s.taskPerformance?.elu?.active??0),q(t.elu.idle,r,s.taskPerformance?.elu?.idle??0),r.aggregate&&null!=s.taskPerformance?.elu&&(null!=t.elu.utilization?t.elu.utilization=(t.elu.utilization+s.taskPerformance.elu.utilization)/2:t.elu.utilization=s.taskPerformance.elu.utilization)},B=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class D{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:p,waitTime:p,elu:p};constructor(e,t=w){this.pool=e,this.opts=t,this.opts={...w,...t},this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.runTime,e.runTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.waitTime,e.waitTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.elu,e.elu?.median)}toggleMedianMeasurementStatisticsRequirements(e,t){e.average&&t&&(e.average=!1,e.median=t),e.median&&!t&&(e.average=!0,e.median=t)}resetWorkerNodeKeyProperties(){this.nextWorkerNodeKey=0,this.previousWorkerNodeKey=0}setOptions(e){this.opts={...w,...e},this.setTaskStatisticsRequirements(this.opts)}hasPoolWorkerNodesReady(){return this.pool.workerNodes.some((e=>e.info.ready))}isWorkerNodeReady(e){return this.pool.workerNodes[e]?.info?.ready??!1}checkNextWorkerNodeReadiness(){this.isWorkerNodeReady(this.nextWorkerNodeKey)||delete this.nextWorkerNodeKey}getWorkerNodeTaskRunTime(e){return this.taskStatisticsRequirements.runTime.median?this.pool.workerNodes[e].usage.runTime.median??0:this.pool.workerNodes[e].usage.runTime.average??0}getWorkerNodeTaskWaitTime(e){return this.taskStatisticsRequirements.waitTime.median?this.pool.workerNodes[e].usage.waitTime.median??0:this.pool.workerNodes[e].usage.waitTime.average??0}getWorkerNodeTaskElu(e){return this.taskStatisticsRequirements.elu.median?this.pool.workerNodes[e].usage.elu.active.median??0:this.pool.workerNodes[e].usage.elu.active.average??0}setPreviousWorkerNodeKey(e){this.previousWorkerNodeKey=e??this.previousWorkerNodeKey}computeDefaultWorkerWeight(){let e=0;for(const t of i.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/i.cpus().length)}}class L extends D{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:{aggregate:!0,average:!0,median:!1}};constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){for(const e of this.pool.workerNodes)delete e.strategyData?.virtualTaskEndTimestamp;return!0}update(e){return this.pool.workerNodes[e].strategyData={virtualTaskEndTimestamp:this.computeWorkerNodeVirtualTaskEndTimestamp(e)},!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.fairShareNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}fairShareNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>(null==t.strategyData?.virtualTaskEndTimestamp&&(t.strategyData={virtualTaskEndTimestamp:this.computeWorkerNodeVirtualTaskEndTimestamp(s)}),this.isWorkerNodeReady(s)&&t.strategyData.virtualTaskEndTimestamp<r[e].strategyData.virtualTaskEndTimestamp?s:e)),0)}computeWorkerNodeVirtualTaskEndTimestamp(e){return this.getWorkerNodeVirtualTaskEndTimestamp(e,this.getWorkerNodeVirtualTaskStartTimestamp(e))}getWorkerNodeVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===O.elu?this.getWorkerNodeTaskElu(e):this.getWorkerNodeTaskRunTime(e))}getWorkerNodeVirtualTaskStartTimestamp(e){const t=this.pool.workerNodes[e]?.strategyData?.virtualTaskEndTimestamp,s=performance.now();return s<(t??-1/0)?t:s}}class H extends D{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};roundId=0;defaultWorkerWeight;roundWeights;workerNodeId=0;workerNodeVirtualTaskRunTime=0;constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,this.workerNodeId=0,this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){for(let e=this.roundId;e<this.roundWeights.length;e++){this.roundId=e;for(let t=this.workerNodeId;t<this.pool.workerNodes.length;t++){this.workerNodeId=t,this.workerNodeId!==this.nextWorkerNodeKey&&0!==this.workerNodeVirtualTaskRunTime&&(this.workerNodeVirtualTaskRunTime=0);const s=this.opts.weights?.[t]??this.defaultWorkerWeight;if(this.isWorkerNodeReady(t)&&s>=this.roundWeights[e]&&this.workerNodeVirtualTaskRunTime<s)return this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(t),this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=t,this.nextWorkerNodeKey}}this.interleavedWeightedRoundRobinNextWorkerNodeId()}interleavedWeightedRoundRobinNextWorkerNodeId(){this.roundId===this.roundWeights.length-1&&this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=0,this.workerNodeId=0):this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=this.roundId+1,this.workerNodeId=0):this.workerNodeId=this.workerNodeId+1}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.workerNodeId===e&&this.workerNodeId>this.pool.workerNodes.length-1&&(this.workerNodeId=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}setOptions(e){super.setOptions(e),this.roundWeights=this.getRoundWeights()}getRoundWeights(){return null==this.opts.weights?[this.defaultWorkerWeight]:[...new Set(Object.values(this.opts.weights).slice().sort(((e,t)=>e-t)))]}}class _ extends D{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:p};constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastBusyNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastBusyNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>this.isWorkerNodeReady(s)&&(t.usage.runTime.aggregate??0)+(t.usage.waitTime.aggregate??0)<(r[e].usage.runTime.aggregate??0)+(r[e].usage.waitTime.aggregate??0)?s:e),0)}}class j extends D{constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>this.isWorkerNodeReady(s)&&t.usage.tasks.executed+t.usage.tasks.executing+t.usage.tasks.queued<r[e].usage.tasks.executed+r[e].usage.tasks.executing+r[e].usage.tasks.queued?s:e),0)}}class V extends D{taskStatisticsRequirements={runTime:p,waitTime:p,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastEluNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastEluNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>this.isWorkerNodeReady(s)&&(t.usage.elu.active.aggregate??0)<(r[e].usage.elu.active.aggregate??0)?s:e),0)}}class $ extends D{constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.setPreviousWorkerNodeKey(e),this.roundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeReadiness(),e}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}roundRobinNextWorkerNodeKey(){return this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.nextWorkerNodeKey}}class G extends D{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};defaultWorkerWeight;workerNodeVirtualTaskRunTime=0;constructor(e,t=w){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.weightedRoundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeReadiness(),this.nextWorkerNodeKey}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&(this.workerNodeVirtualTaskRunTime=0,this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight;return this.workerNodeVirtualTaskRunTime<e?this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerNodeVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class Y{workerChoiceStrategy;opts;workerChoiceStrategies;constructor(e,t=b.ROUND_ROBIN,s=w){this.workerChoiceStrategy=t,this.opts=s,this.opts={...w,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[b.ROUND_ROBIN,new($.bind(this))(e,s)],[b.LEAST_USED,new(j.bind(this))(e,s)],[b.LEAST_BUSY,new(_.bind(this))(e,s)],[b.LEAST_ELU,new(V.bind(this))(e,s)],[b.FAIR_SHARE,new(L.bind(this))(e,s)],[b.WEIGHTED_ROUND_ROBIN,new(G.bind(this))(e,s)],[b.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(H.bind(this))(e,s)]])}getStrategyPolicy(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).strategyPolicy}getTaskStatisticsRequirements(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).taskStatisticsRequirements}setWorkerChoiceStrategy(e){this.workerChoiceStrategy!==e&&(this.workerChoiceStrategy=e),this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()}update(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).update(e)}execute(){const e=this.workerChoiceStrategies.get(this.workerChoiceStrategy);let t;const s=1e4;let r=0,i=0,o=0;do{e.hasPoolWorkerNodesReady()&&(t=e.choose(),i>0&&o++,i++),r++}while(r<s&&(!e.hasPoolWorkerNodesReady()||null==t&&o<this.opts.retries));if(r>=s)throw new RangeError("Worker choice strategy consecutive executions has exceeded the maximum of 10000");if(null==t)throw new Error(`Worker node key chosen is null or undefined after ${o} retries`);return t}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...w,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class J extends Array{size;constructor(e=1024,...t){super(),this.checkSize(e),this.size=e,arguments.length>1&&this.push(...t)}push(...e){const t=super.push(...e);return t>this.size&&super.splice(0,t-this.size),this.length}unshift(...e){return super.unshift(...e)>this.size&&super.splice(this.size,e.length),this.length}concat(...e){const t=super.concat(e);return t.size=this.size,t.length>t.size&&t.splice(0,t.length-t.size),t}splice(e,t,...s){let r=[];if(arguments.length>=3&&null!=t){if(r=super.splice(e,t,...s),this.length>this.size){const e=super.splice(0,this.length-this.size);r=new J(r.length+e.length,...r,...e)}}else r=2===arguments.length?super.splice(e,t):super.splice(e);return r}resize(e){if(this.checkSize(e),0===e)this.length=0;else if(e<this.size)for(let t=e;t<this.size;t++)super.pop();this.size=e}empty(){return 0===this.length}full(){return this.length===this.size}checkSize(e){if(!Number.isSafeInteger(e))throw new TypeError(`Invalid circular array size: ${e} is not a safe integer`);if(e<0)throw new RangeError(`Invalid circular array size: ${e} < 0`)}}class X{data;next;prev;constructor(e){this.data=e}}class Z{head;tail;size;maxSize;constructor(){this.clear()}push(e){const t=new X(e);return null==this.tail?this.head=this.tail=t:(t.prev=this.tail,this.tail=this.tail.next=t),this.incrementSize()}unshift(e){const t=new X(e);return null==this.head?this.head=this.tail=t:(t.next=this.head,this.head=this.head.prev=t),this.incrementSize()}pop(){if(null==this.head)return;const e=this.tail;return this.tail=this.tail.prev,null==this.tail?delete this.head:delete this.tail.next,--this.size,e?.data}shift(){if(null==this.head)return;const e=this.head;return this.head=this.head.next,null==this.head?delete this.tail:delete this.head.prev,--this.size,e?.data}peekFirst(){return this.head?.data}peekLast(){return this.tail?.data}clear(){delete this.head,delete this.tail,this.size=0,this.maxSize=0}[Symbol.iterator](){let e=this.head;return{next:()=>{if(null==e)return{value:void 0,done:!0};const t={value:e.data,done:!1};return e=e.next,t}}}backward(){return{[Symbol.iterator]:()=>{let e=this.tail;return{next:()=>{if(null==e)return{value:void 0,done:!0};const t={value:e.data,done:!1};return e=e.prev,t}}}}}incrementSize(){return++this.size,this.size>this.maxSize&&(this.maxSize=this.size),this.size}}class ee extends a.EventEmitter{worker;info;usage;strategyData;messageChannel;tasksQueueBackPressureSize;tasksQueue;onBackPressureStarted;taskFunctionsUsage;constructor(t,r,i){super(),((e,t,s)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker type");if(!Object.values(l).includes(e))throw new TypeError(`Cannot construct a worker node with an invalid worker type '${e}'`);if(R(t),null==s)throw new TypeError("Cannot construct a worker node without worker node options");if(!S(s))throw new TypeError("Cannot construct a worker node with invalid options: must be a plain object");if(null==s.tasksQueueBackPressureSize)throw new TypeError("Cannot construct a worker node without a tasks queue back pressure size option");if(!Number.isSafeInteger(s.tasksQueueBackPressureSize))throw new TypeError("Cannot construct a worker node with a tasks queue back pressure size option that is not an integer");if(s.tasksQueueBackPressureSize<=0)throw new RangeError("Cannot construct a worker node with a tasks queue back pressure size option that is not a positive integer")})(t,r,i),this.worker=((t,r,i)=>{switch(t){case l.thread:return new s.Worker(r,{env:s.SHARE_ENV,...i?.workerOptions});case l.cluster:return e.fork(i?.env);default:throw new Error(`Unknown worker type '${t}'`)}})(t,r,{env:i.env,workerOptions:i.workerOptions}),this.info=this.initWorkerInfo(this.worker),this.usage=this.initWorkerUsage(),this.info.type===l.thread&&(this.messageChannel=new s.MessageChannel),this.tasksQueueBackPressureSize=i.tasksQueueBackPressureSize,this.tasksQueue=new Z,this.onBackPressureStarted=!1,this.taskFunctionsUsage=new Map}tasksQueueSize(){return this.tasksQueue.size}enqueueTask(e){const t=this.tasksQueue.push(e);return this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.emit("backPressure",{workerId:this.info.id}),this.onBackPressureStarted=!1),t}unshiftTask(e){const t=this.tasksQueue.unshift(e);return this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.emit("backPressure",{workerId:this.info.id}),this.onBackPressureStarted=!1),t}dequeueTask(){return this.tasksQueue.shift()}popTask(){return this.tasksQueue.pop()}clearTasksQueue(){this.tasksQueue.clear()}hasBackPressure(){return this.tasksQueue.size>=this.tasksQueueBackPressureSize}resetUsage(){this.usage=this.initWorkerUsage(),this.taskFunctionsUsage.clear()}async terminate(){const e=new Promise((e=>{this.registerOnceWorkerEventHandler("exit",(()=>{e()}))}));this.closeMessageChannel(),this.removeAllListeners(),this.info.type===l.thread?await(this.worker.terminate?.()):this.info.type===l.cluster&&(this.registerOnceWorkerEventHandler("disconnect",(()=>{this.worker.kill?.()})),this.worker.disconnect?.()),await e}registerWorkerEventHandler(e,t){this.worker.on(e,t)}registerOnceWorkerEventHandler(e,t){this.worker.once(e,t)}getTaskFunctionWorkerUsage(e){if(!Array.isArray(this.info.taskFunctionNames))throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list is not yet defined`);if(Array.isArray(this.info.taskFunctionNames)&&this.info.taskFunctionNames.length<3)throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list has less than 3 elements`);return e===g&&(e=this.info.taskFunctionNames[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}deleteTaskFunctionWorkerUsage(e){return this.taskFunctionsUsage.delete(e)}closeMessageChannel(){null!=this.messageChannel&&(this.messageChannel.port1.unref(),this.messageChannel.port2.unref(),this.messageChannel.port1.close(),this.messageChannel.port2.close(),delete this.messageChannel)}initWorkerInfo(e){return{id:T(e),type:y(e),dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueue.size,t=()=>this.tasksQueue.maxSize;return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},sequentiallyStolen:0,stolen:0,failed:0},runTime:{history:new J},waitTime:{history:new J},elu:{idle:{history:new J},active:{history:new J}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===g&&e===this.info.taskFunctionNames[1]||s.name!==g&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},sequentiallyStolen:0,stolen:0,failed:0},runTime:{history:new J},waitTime:{history:new J},elu:{idle:{history:new J},active:{history:new J}}}}}class te{numberOfWorkers;filePath;opts;workerNodes=[];emitter;max;promiseResponseMap=new Map;workerChoiceStrategyContext;taskFunctions;started;starting;destroying;readyEventEmitted;startTimestamp;constructor(e,t,s){if(this.numberOfWorkers=e,this.filePath=t,this.opts=s,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");R(this.filePath),this.checkNumberOfWorkers(this.numberOfWorkers),this.checkPoolOptions(this.opts),this.chooseWorkerNode=this.chooseWorkerNode.bind(this),this.executeTask=this.executeTask.bind(this),this.enqueueTask=this.enqueueTask.bind(this),!0===this.opts.enableEvents&&this.initializeEventEmitter(),this.workerChoiceStrategyContext=new Y(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.taskFunctions=new Map,this.started=!1,this.starting=!1,this.destroying=!1,this.readyEventEmitted=!1,!0===this.opts.startWorkers&&this.start(),this.startTimestamp=n.performance.now()}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new TypeError("Cannot instantiate a pool with a non safe integer number of workers");if(e<0)throw new RangeError("Cannot instantiate a pool with a negative number of workers");if(this.type===d.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkPoolOptions(e){if(!S(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.startWorkers=e.startWorkers??!0,P(e.workerChoiceStrategy),this.opts.workerChoiceStrategy=e.workerChoiceStrategy??b.ROUND_ROBIN,this.checkValidWorkerChoiceStrategyOptions(e.workerChoiceStrategyOptions),this.opts.workerChoiceStrategyOptions={...w,...e.workerChoiceStrategyOptions},this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(M(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategyOptions(e){if(null!=e&&!S(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e?.retries&&!Number.isSafeInteger(e.retries))throw new TypeError("Invalid worker choice strategy options: retries must be an integer");if(null!=e?.retries&&e.retries<0)throw new RangeError(`Invalid worker choice strategy options: retries '${e.retries}' must be greater or equal than zero`);if(null!=e?.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e?.measurement&&!Object.values(O).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}initializeEventEmitter(){this.emitter=new a.EventEmitterAsyncResource({name:`poolifier:${this.type}-${this.worker}-pool`})}get info(){return{version:"3.1.6",type:this.type,worker:this.worker,started:this.started,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:W(this.utilization)},workerNodes:this.workerNodes.length,idleWorkerNodes:this.workerNodes.reduce(((e,t)=>0===t.usage.tasks.executing?e+1:e),0),busyWorkerNodes:this.workerNodes.reduce(((e,t,s)=>this.isWorkerNodeBusy(s)?e+1:e),0),executedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executed),0),executingTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executing),0),...!0===this.opts.enableTasksQueue&&{queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0)},...!0===this.opts.enableTasksQueue&&{maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.maxQueued??0)),0)},...!0===this.opts.enableTasksQueue&&{backPressure:this.hasBackPressure()},...!0===this.opts.enableTasksQueue&&{stolenTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.stolen),0)},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:W(I(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:W(F(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&{average:W(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:W(N(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:W(I(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:W(F(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&{average:W(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:W(N(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(n.performance.now()-this.startTimestamp)*this.maxSize;return(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)+this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0))/e}get minSize(){return this.numberOfWorkers}get maxSize(){return this.max??this.numberOfWorkers}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Worker message received without worker id");if(-1===this.getWorkerNodeKeyByWorkerId(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKeyByWorkerId(e){return this.workerNodes.findIndex((t=>t.info.id===e))}setWorkerChoiceStrategy(e,t){P(e),this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(this.opts.workerChoiceStrategy),null!=t&&this.setWorkerChoiceStrategyOptions(t);for(const[e,t]of this.workerNodes.entries())t.resetUsage(),this.sendStatisticsMessageToWorker(e)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions={...w,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||(this.unsetTaskStealing(),this.unsetTasksStealingOnBackPressure(),this.flushTasksQueues()),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(M(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e),this.setTasksQueueSize(this.opts.tasksQueueOptions.size),!0===this.opts.tasksQueueOptions.taskStealing?(this.unsetTaskStealing(),this.setTaskStealing()):this.unsetTaskStealing(),!0===this.opts.tasksQueueOptions.tasksStealingOnBackPressure?(this.unsetTasksStealingOnBackPressure(),this.setTasksStealingOnBackPressure()):this.unsetTasksStealingOnBackPressure()):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{...C(this.maxSize),...e}}setTasksQueueSize(e){for(const t of this.workerNodes)t.tasksQueueBackPressureSize=e}setTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].on("idleWorkerNode",this.handleIdleWorkerNodeEvent)}unsetTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].off("idleWorkerNode",this.handleIdleWorkerNodeEvent)}setTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].on("backPressure",this.handleBackPressureEvent)}unsetTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].off("backPressure",this.handleBackPressureEvent)}get full(){return this.workerNodes.length>=this.maxSize}internalBusy(){return!0===this.opts.enableTasksQueue?-1===this.workerNodes.findIndex((e=>e.info.ready&&e.usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency)):-1===this.workerNodes.findIndex((e=>e.info.ready&&0===e.usage.tasks.executing))}isWorkerNodeBusy(e){return!0===this.opts.enableTasksQueue?this.workerNodes[e].usage.tasks.executing>=this.opts.tasksQueueOptions?.concurrency:this.workerNodes[e].usage.tasks.executing>0}async sendTaskFunctionOperationToWorker(e,t){return await new Promise(((s,r)=>{const i=t=>{this.checkMessageWorkerId(t);const o=this.getWorkerInfo(e).id;null!=t.taskFunctionOperationStatus&&t.workerId===o&&(t.taskFunctionOperationStatus?s(!0):t.taskFunctionOperationStatus||r(new Error(`Task function operation '${t.taskFunctionOperation}' failed on worker ${t.workerId} with error: '${t.workerError?.message}'`)),this.deregisterWorkerMessageListener(this.getWorkerNodeKeyByWorkerId(t.workerId),i))};this.registerWorkerMessageListener(e,i),this.sendToWorker(e,t)}))}async sendTaskFunctionOperationToWorkers(e){return await new Promise(((t,s)=>{const r=new Array,i=e=>{if(this.checkMessageWorkerId(e),null!=e.taskFunctionOperationStatus&&(r.push(e),r.length===this.workerNodes.length)){if(r.every((e=>!0===e.taskFunctionOperationStatus)))t(!0);else if(r.some((e=>!1===e.taskFunctionOperationStatus))){const t=r.find((e=>!1===e.taskFunctionOperationStatus));s(new Error(`Task function operation '${e.taskFunctionOperation}' failed on worker ${t?.workerId} with error: '${t?.workerError?.message}'`))}this.deregisterWorkerMessageListener(this.getWorkerNodeKeyByWorkerId(e.workerId),i)}};for(const[t]of this.workerNodes.entries())this.registerWorkerMessageListener(t,i),this.sendToWorker(t,e)}))}hasTaskFunction(e){for(const t of this.workerNodes)if(Array.isArray(t.info.taskFunctionNames)&&t.info.taskFunctionNames.includes(e))return!0;return!1}async addTaskFunction(e,t){if("string"!=typeof e)throw new TypeError("name argument must be a string");if("string"==typeof e&&0===e.trim().length)throw new TypeError("name argument must not be an empty string");if("function"!=typeof t)throw new TypeError("fn argument must be a function");const s=await this.sendTaskFunctionOperationToWorkers({taskFunctionOperation:"add",taskFunctionName:e,taskFunction:t.toString()});return this.taskFunctions.set(e,t),s}async removeTaskFunction(e){if(!this.taskFunctions.has(e))throw new Error("Cannot remove a task function not handled on the pool side");const t=await this.sendTaskFunctionOperationToWorkers({taskFunctionOperation:"remove",taskFunctionName:e});return this.deleteTaskFunctionWorkerUsages(e),this.taskFunctions.delete(e),t}listTaskFunctionNames(){for(const e of this.workerNodes)if(Array.isArray(e.info.taskFunctionNames)&&e.info.taskFunctionNames.length>0)return e.info.taskFunctionNames;return[]}async setDefaultTaskFunction(e){return await this.sendTaskFunctionOperationToWorkers({taskFunctionOperation:"default",taskFunctionName:e})}deleteTaskFunctionWorkerUsages(e){for(const t of this.workerNodes)t.deleteTaskFunctionWorkerUsage(e)}shallExecuteTask(e){return 0===this.tasksQueueSize(e)&&this.workerNodes[e].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency}async execute(e,t,s){return await new Promise(((r,i)=>{if(!this.started)return void i(new Error("Cannot execute a task on not started pool"));if(this.destroying)return void i(new Error("Cannot execute a task on destroying pool"));if(null!=t&&"string"!=typeof t)return void i(new TypeError("name argument must be a string"));if(null!=t&&"string"==typeof t&&0===t.trim().length)return void i(new TypeError("name argument must not be an empty string"));if(null!=s&&!Array.isArray(s))return void i(new TypeError("transferList argument must be an array"));const a=n.performance.now(),h=this.chooseWorkerNode(),k={name:t??g,data:e??{},transferList:s,timestamp:a,taskId:o.randomUUID()};this.promiseResponseMap.set(k.taskId,{resolve:r,reject:i,workerNodeKey:h,...null!=this.emitter&&{asyncResource:new u.AsyncResource("poolifier:task",{triggerAsyncId:this.emitter.asyncId,requireManualDestroy:!0})}}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.shallExecuteTask(h)?this.executeTask(h,k):this.enqueueTask(h,k)}))}start(){if(this.started)throw new Error("Cannot start an already started pool");if(this.starting)throw new Error("Cannot start an already starting pool");if(this.destroying)throw new Error("Cannot start a destroying pool");for(this.starting=!0;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode();this.starting=!1,this.started=!0}async destroy(){if(!this.started)throw new Error("Cannot destroy an already destroyed pool");if(this.starting)throw new Error("Cannot destroy an starting pool");if(this.destroying)throw new Error("Cannot destroy an already destroying pool");this.destroying=!0,await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(c.destroy,this.info),this.emitter?.emitDestroy(),this.emitter?.removeAllListeners(),this.readyEventEmitted=!1,this.destroying=!1,this.started=!1}async sendKillMessageToWorker(e){await new Promise(((t,s)=>{if(e<0||e>=this.workerNodes.length)return void s(new Error(`Invalid worker node key '${e}'`));this.registerWorkerMessageListener(e,(e=>{this.checkMessageWorkerId(e),"success"===e.kill?t():"failure"===e.kill&&s(new Error(`Kill message handling failed on worker ${e.workerId}`))})),this.sendToWorker(e,{kill:!0})}))}async destroyWorkerNode(e){this.flagWorkerNodeAsNotReady(e);const t=this.flushTasksQueue(e),s=this.workerNodes[e];await(async(e,t,s,r)=>await new Promise((i=>{let o=0;0!==s?(e.on(t,(()=>{++o,o===s&&i(o)})),r>=0&&setTimeout((()=>{i(o)}),r)):i(o)})))(s,"taskFinished",t,this.opts.tasksQueueOptions?.tasksFinishedTimeout??C(this.maxSize).tasksFinishedTimeout),await this.sendKillMessageToWorker(e),await s.terminate()}setupHook(){}beforeTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;++s.tasks.executing,K(this.workerChoiceStrategyContext,s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,K(this.workerChoiceStrategyContext,s,t)}}afterTaskExecutionHook(e,t){let s=!1;if(null!=this.workerNodes[e]?.usage){const r=this.workerNodes[e].usage;Q(r,t),U(this.workerChoiceStrategyContext,r,t),A(this.workerChoiceStrategyContext,r,t),s=!0}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name)){const r=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name);Q(r,t),U(this.workerChoiceStrategyContext,r,t),A(this.workerChoiceStrategyContext,r,t),s=!0}s&&this.workerChoiceStrategyContext.update(e)}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return null!=t&&Array.isArray(t.taskFunctionNames)&&t.taskFunctionNames.length>2}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorkerNode();if(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===d.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorkerNode();e.registerWorkerEventHandler("online",this.opts.onlineHandler??m),e.registerWorkerEventHandler("message",this.opts.messageHandler??m),e.registerWorkerEventHandler("error",this.opts.errorHandler??m),e.registerWorkerEventHandler("error",(t=>{e.info.ready=!1,this.emitter?.emit(c.error,t),!this.started||this.starting||this.destroying||!0!==this.opts.restartWorkerOnError||(e.info.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),this.started&&!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(this.workerNodes.indexOf(e)),e?.terminate().catch((e=>{this.emitter?.emit(c.error,e)}))})),e.registerWorkerEventHandler("exit",this.opts.exitHandler??m),e.registerOnceWorkerEventHandler("exit",(()=>{this.removeWorkerNode(e)}));const t=this.addWorkerNode(e);return this.afterWorkerNodeSetup(t),t}createAndSetupDynamicWorkerNode(){const e=this.createAndSetupWorkerNode();this.registerWorkerMessageListener(e,(e=>{this.checkMessageWorkerId(e);const t=this.getWorkerNodeKeyByWorkerId(e.workerId),s=this.workerNodes[t].usage;(v(B.HARD,e.kill)||v(B.SOFT,e.kill)&&(!1===this.opts.enableTasksQueue&&0===s.tasks.executing||!0===this.opts.enableTasksQueue&&0===s.tasks.executing&&0===this.tasksQueueSize(t)))&&(this.flagWorkerNodeAsNotReady(t),this.destroyWorkerNode(t).catch((e=>{this.emitter?.emit(c.error,e)})))}));const t=this.getWorkerInfo(e);if(this.sendToWorker(e,{checkActive:!0}),this.taskFunctions.size>0)for(const[t,s]of this.taskFunctions)this.sendTaskFunctionOperationToWorker(e,{taskFunctionOperation:"add",taskFunctionName:t,taskFunction:s.toString()}).catch((e=>{this.emitter?.emit(c.error,e)}));return t.dynamic=!0,(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerReady||this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)&&(t.ready=!0),this.checkAndEmitDynamicWorkerCreationEvents(),e}afterWorkerNodeSetup(e){this.registerWorkerMessageListener(e,this.workerMessageListener),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e),!0===this.opts.enableTasksQueue&&(!0===this.opts.tasksQueueOptions?.taskStealing&&this.workerNodes[e].on("idleWorkerNode",this.handleIdleWorkerNodeEvent),!0===this.opts.tasksQueueOptions?.tasksStealingOnBackPressure&&this.workerNodes[e].on("backPressure",this.handleBackPressureEvent))}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate}})}handleTask(e,t){this.shallExecuteTask(e)?this.executeTask(e,t):this.enqueueTask(e,t)}redistributeQueuedTasks(e){if(-1!==e&&!(this.workerNodes.length<=1))for(;this.tasksQueueSize(e)>0;){const t=this.workerNodes.reduce(((e,t,s,r)=>t.info.ready&&t.usage.tasks.queued<r[e].usage.tasks.queued?s:e),0);this.handleTask(t,this.dequeueTask(e))}}updateTaskStolenStatisticsWorkerUsage(e,t){const s=this.workerNodes[e];if(null!=s?.usage&&++s.usage.tasks.stolen,this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=s.getTaskFunctionWorkerUsage(t)){++s.getTaskFunctionWorkerUsage(t).tasks.stolen}}updateTaskSequentiallyStolenStatisticsWorkerUsage(e){const t=this.workerNodes[e];null!=t?.usage&&++t.usage.tasks.sequentiallyStolen}updateTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(e,t){const s=this.workerNodes[e];if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=s.getTaskFunctionWorkerUsage(t)){++s.getTaskFunctionWorkerUsage(t).tasks.sequentiallyStolen}}resetTaskSequentiallyStolenStatisticsWorkerUsage(e){const t=this.workerNodes[e];null!=t?.usage&&(t.usage.tasks.sequentiallyStolen=0)}resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(e,t){const s=this.workerNodes[e];if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=s.getTaskFunctionWorkerUsage(t)){s.getTaskFunctionWorkerUsage(t).tasks.sequentiallyStolen=0}}handleIdleWorkerNodeEvent=(e,t)=>{if(this.workerNodes.length<=1)return;const{workerNodeKey:s}=e;if(null==s)throw new Error("WorkerNode event detail workerNodeKey attribute must be defined");const r=this.workerNodes[s].usage.tasks;if(null!=t&&r.sequentiallyStolen>0&&(r.executing>0||this.tasksQueueSize(s)>0)){for(const e of this.workerNodes[s].info.taskFunctionNames)this.resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(s,e);return void this.resetTaskSequentiallyStolenStatisticsWorkerUsage(s)}const i=this.workerNodeStealTask(s);if(this.shallUpdateTaskFunctionWorkerUsage(s)&&null!=i){const e=this.workerNodes[s].getTaskFunctionWorkerUsage(i.name)?.tasks;0===e.sequentiallyStolen||null!=t&&t.name===i.name&&e.sequentiallyStolen>0?this.updateTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(s,i.name):this.resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(s,i.name)}(async e=>{await new Promise((t=>{setTimeout(t,e)}))})(((e=0,t=100)=>{const s=Math.pow(2,e)*t;return s+.2*s*E()})(r.sequentiallyStolen)).then((()=>{this.handleIdleWorkerNodeEvent(e,i)})).catch(m)};workerNodeStealTask=e=>{const t=this.workerNodes.slice().sort(((e,t)=>t.usage.tasks.queued-e.usage.tasks.queued)).find(((t,s)=>t.info.ready&&s!==e&&t.usage.tasks.queued>0));if(null!=t){const s=t.popTask();return this.handleTask(e,s),this.updateTaskSequentiallyStolenStatisticsWorkerUsage(e),this.updateTaskStolenStatisticsWorkerUsage(e,s.name),s}};handleBackPressureEvent=e=>{if(this.workerNodes.length<=1)return;const{workerId:t}=e;if(this.opts.tasksQueueOptions?.size<=1)return;const s=this.workerNodes[this.getWorkerNodeKeyByWorkerId(t)],r=this.workerNodes.slice().sort(((e,t)=>e.usage.tasks.queued-t.usage.tasks.queued));for(const[e,i]of r.entries())if(s.usage.tasks.queued>0&&i.info.ready&&i.info.id!==t&&i.usage.tasks.queued<this.opts.tasksQueueOptions?.size-1){const t=s.popTask();this.handleTask(e,t),this.updateTaskStolenStatisticsWorkerUsage(e,t.name)}};workerMessageListener=e=>{this.checkMessageWorkerId(e);const{workerId:t,ready:s,taskId:r,taskFunctionNames:i}=e;null!=s&&null!=i?this.handleWorkerReadyResponse(e):null!=r?this.handleTaskExecutionResponse(e):null!=i&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(t)).taskFunctionNames=i)};handleWorkerReadyResponse(e){const{workerId:t,ready:s,taskFunctionNames:r}=e;if(!1===s)throw new Error(`Worker ${t} failed to initialize`);const i=this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(t));i.ready=s,i.taskFunctionNames=r,!this.readyEventEmitted&&this.ready&&(this.readyEventEmitted=!0,this.emitter?.emit(c.ready,this.info))}handleTaskExecutionResponse(e){const{workerId:t,taskId:s,workerError:r,data:i}=e,o=this.promiseResponseMap.get(s);if(null!=o){const{resolve:n,reject:a,workerNodeKey:u,asyncResource:h}=o,k=this.workerNodes[u];if(null!=r?(this.emitter?.emit(c.taskError,r),null!=h?h.runInAsyncScope(a,this.emitter,r.message):a(r.message)):null!=h?h.runInAsyncScope(n,this.emitter,i):n(i),h?.emitDestroy(),this.afterTaskExecutionHook(u,e),this.promiseResponseMap.delete(s),k?.emit("taskFinished",s),!0===this.opts.enableTasksQueue&&!this.destroying){const e=k.usage.tasks;this.tasksQueueSize(u)>0&&e.executing<this.opts.tasksQueueOptions?.concurrency&&this.executeTask(u,this.dequeueTask(u)),0===e.executing&&0===this.tasksQueueSize(u)&&0===e.sequentiallyStolen&&k.emit("idleWorkerNode",{workerId:t,workerNodeKey:u})}}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(c.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(c.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===d.dynamic&&this.full&&this.emitter?.emit(c.full,this.info)}getWorkerInfo(e){return this.workerNodes[e]?.info}createWorkerNode(){const e=new ee(this.worker,this.filePath,{env:this.opts.env,workerOptions:this.opts.workerOptions,tasksQueueBackPressureSize:this.opts.tasksQueueOptions?.size??C(this.maxSize).size});return this.starting&&(e.info.ready=!0),e}addWorkerNode(e){this.workerNodes.push(e);const t=this.workerNodes.indexOf(e);if(-1===t)throw new Error("Worker added not found in worker nodes");return t}removeWorkerNode(e){const t=this.workerNodes.indexOf(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}flagWorkerNodeAsNotReady(e){this.getWorkerInfo(e).ready=!1}hasWorkerNodeBackPressure(e){return!0===this.opts.enableTasksQueue&&this.workerNodes[e].hasBackPressure()}hasBackPressure(){return!0===this.opts.enableTasksQueue&&-1===this.workerNodes.findIndex((e=>!e.hasBackPressure()))}executeTask(e,t){this.beforeTaskExecutionHook(e,t),this.sendToWorker(e,t,t.transferList),this.checkAndEmitTaskExecutionEvents()}enqueueTask(e,t){const s=this.workerNodes[e].enqueueTask(t);return this.checkAndEmitTaskQueuingEvents(),s}dequeueTask(e){return this.workerNodes[e].dequeueTask()}tasksQueueSize(e){return this.workerNodes[e].tasksQueueSize()}flushTasksQueue(e){let t=0;for(;this.tasksQueueSize(e)>0;)this.executeTask(e,this.dequeueTask(e)),++t;return this.workerNodes[e].clearTasksQueue(),t}flushTasksQueues(){for(const[e]of this.workerNodes.entries())this.flushTasksQueue(e)}}class se extends te{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){e.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return e.isPrimary}sendToWorker(e,t){this.workerNodes[e].worker.send({...t,workerId:this.getWorkerInfo(e).id})}sendStartupMessageToWorker(e){this.sendToWorker(e,{ready:!1})}registerWorkerMessageListener(e,t){this.workerNodes[e].worker.on("message",t)}registerOnceWorkerMessageListener(e,t){this.workerNodes[e].worker.once("message",t)}deregisterWorkerMessageListener(e,t){this.workerNodes[e].worker.off("message",t)}get type(){return d.fixed}get worker(){return l.cluster}get busy(){return this.internalBusy()}}class re extends te{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return s.isMainThread}sendToWorker(e,t,s){this.workerNodes[e].messageChannel?.port1?.postMessage({...t,workerId:this.getWorkerInfo(e).id},s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e],s=t.messageChannel.port2;t.worker.postMessage({ready:!1,workerId:this.getWorkerInfo(e).id,port:s},[s])}registerWorkerMessageListener(e,t){this.workerNodes[e].messageChannel?.port1?.on("message",t)}registerOnceWorkerMessageListener(e,t){this.workerNodes[e].messageChannel?.port1?.once("message",t)}deregisterWorkerMessageListener(e,t){this.workerNodes[e].messageChannel?.port1?.off("message",t)}get type(){return d.fixed}get worker(){return l.thread}get busy(){return this.internalBusy()}}const ie=(e,t)=>{if("string"!=typeof e)throw new TypeError("A taskFunctions parameter object key is not a string");if("string"==typeof e&&0===e.trim().length)throw new TypeError("A taskFunctions parameter object key is an empty string");if("function"!=typeof t)throw new TypeError("A taskFunctions parameter object value is not a function")},oe=e=>{if("string"!=typeof e)throw new TypeError("name parameter is not a string");if("string"==typeof e&&0===e.trim().length)throw new TypeError("name parameter is an empty string")},ne=6e4,ae={killBehavior:B.SOFT,maxInactiveTime:ne,killHandler:m};class ue{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r=ae){if(this.isMain=e,this.mainWorker=t,this.opts=r,null==this.isMain)throw new Error("isMain parameter is mandatory");this.checkTaskFunctions(s),this.checkWorkerOptions(this.opts),this.isMain||this.getMainWorker().on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){(e=>{if(null!=e&&!S(e))throw new TypeError("opts worker options parameter is not a plain object");if(null!=e?.killBehavior&&!Object.values(B).includes(e.killBehavior))throw new TypeError(`killBehavior option '${e.killBehavior}' is not valid`);if(null!=e?.maxInactiveTime&&!Number.isSafeInteger(e.maxInactiveTime))throw new TypeError("maxInactiveTime option is not an integer");if(null!=e?.maxInactiveTime&&e.maxInactiveTime<5)throw new TypeError("maxInactiveTime option is not a positive integer greater or equal than 5");if(null!=e?.killHandler&&"function"!=typeof e.killHandler)throw new TypeError("killHandler option is not a function")})(e),this.opts={...ae,...e}}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e){const t=e.bind(this);this.taskFunctions.set(g,t),this.taskFunctions.set("string"==typeof e.name&&e.name.trim().length>0?e.name:"fn1",t)}else{if(!S(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){ie(s,r);const e=r.bind(this);t&&(this.taskFunctions.set(g,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){try{oe(e)}catch(e){return{status:!1,error:e}}return{status:this.taskFunctions.has(e)}}addTaskFunction(e,t){try{if(oe(e),e===g)throw new Error("Cannot add a task function with the default reserved name");if("function"!=typeof t)throw new TypeError("fn parameter is not a function");const s=t.bind(this);return this.taskFunctions.get(e)===this.taskFunctions.get(g)&&this.taskFunctions.set(g,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(oe(e),e===g)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(g))throw new Error("Cannot remove the task function used as the default task function");const t=this.taskFunctions.delete(e);return this.sendTaskFunctionNamesToMainWorker(),{status:t}}catch(e){return{status:!1,error:e}}}listTaskFunctionNames(){const e=[...this.taskFunctions.keys()];let t=g;for(const[e,s]of this.taskFunctions)if(e!==g&&s===this.taskFunctions.get(g)){t=e;break}return[e[e.indexOf(g)],t,...e.filter((e=>e!==g&&e!==t))]}setDefaultTaskFunction(e){try{if(oe(e),e===g)throw new Error("Cannot set the default task function reserved name as the default task function");if(!this.taskFunctions.has(e))throw new Error("Cannot set the default task function to a non-existing task function");return this.taskFunctions.set(g,this.taskFunctions.get(e)),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskFunctionOperation?this.handleTaskFunctionOperationMessage(e):null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleTaskFunctionOperationMessage(e){const{taskFunctionOperation:t,taskFunctionName:s,taskFunction:r}=e;let i;switch(t){case"add":i=this.addTaskFunction(s,new Function(`return ${r}`)());break;case"remove":i=this.removeTaskFunction(s);break;case"default":i=this.setDefaultTaskFunction(s);break;default:i={status:!1,error:new Error("Unknown task operation")}}this.sendToMainWorker({taskFunctionOperation:t,taskFunctionOperationStatus:i.status,taskFunctionName:s,...!i.status&&null!=i?.error&&{workerError:{name:s,message:this.handleError(i.error)}}})}handleKillMessage(e){if(this.stopCheckActive(),x(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>{this.sendToMainWorker({kill:"success"})})).catch((()=>{this.sendToMainWorker({kill:"failure"})}));else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success"})}catch{this.sendToMainWorker({kill:"failure"})}}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Message worker id is not set");if(e.workerId!==this.id)throw new Error(`Message worker id ${e.workerId} does not match the worker id ${this.id}`)}startCheckActive(){this.lastTaskTimestamp=n.performance.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??ne)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){n.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??ne)&&this.sendToMainWorker({kill:this.opts.killBehavior})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}sendTaskFunctionNamesToMainWorker(){this.sendToMainWorker({taskFunctionNames:this.listTaskFunctionNames()})}handleError(e){return e instanceof Error?e.message:e}run=e=>{const{name:t,taskId:s,data:r}=e,i=t??g;if(!this.taskFunctions.has(i))return void this.sendToMainWorker({workerError:{name:t,message:`Task function '${t}' not found`,data:r},taskId:s});const o=this.taskFunctions.get(i);x(o)?this.runAsync(o,e):this.runSync(o,e)};runSync=(e,t)=>{const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,taskId:r})}catch(e){this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})}finally{this.updateLastTaskTimestamp()}};runAsync=(e,t)=>{const{name:s,taskId:r,data:i}=t;let o=this.beginTaskPerformance(s);e(i).then((e=>{o=this.endTaskPerformance(o),this.sendToMainWorker({data:e,taskPerformance:o,taskId:r})})).catch((e=>{this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(m)};beginTaskPerformance(e){return this.checkStatistics(),{name:e??g,timestamp:n.performance.now(),...this.statistics.elu&&{elu:n.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:n.performance.now()-e.timestamp},...this.statistics.elu&&{elu:n.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=n.performance.now())}}exports.ClusterWorker=class extends ue{constructor(t,s={}){super(e.isPrimary,e.worker,t,s)}handleReadyMessage(e){if(e.workerId===this.id&&!1===e.ready)try{this.getMainWorker().on("message",this.messageListener.bind(this)),this.sendToMainWorker({ready:!0,taskFunctionNames:this.listTaskFunctionNames()})}catch{this.sendToMainWorker({ready:!1,taskFunctionNames:this.listTaskFunctionNames()})}}get id(){return this.getMainWorker().id}sendToMainWorker=e=>{this.getMainWorker().send({...e,workerId:this.id})}},exports.DynamicClusterPool=class extends se{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,z(this.numberOfWorkers,this.max)}get type(){return d.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends re{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,z(this.numberOfWorkers,this.max)}get type(){return d.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=se,exports.FixedThreadPool=re,exports.KillBehaviors=B,exports.Measurements=O,exports.PoolEvents=c,exports.PoolTypes=d,exports.ThreadWorker=class extends ue{port;constructor(e,t={}){super(s.isMainThread,s.parentPort,e,t)}handleReadyMessage(e){if(e.workerId===this.id&&!1===e.ready&&null!=e.port)try{this.port=e.port,this.port.on("message",this.messageListener.bind(this)),this.sendToMainWorker({ready:!0,taskFunctionNames:this.listTaskFunctionNames()})}catch{this.sendToMainWorker({ready:!1,taskFunctionNames:this.listTaskFunctionNames()})}}handleKillMessage(e){super.handleKillMessage(e),this.port?.unref(),this.port?.close()}get id(){return s.threadId}sendToMainWorker=e=>{this.port?.postMessage({...e,workerId:this.id})};handleError(e){return e}},exports.WorkerChoiceStrategies=b,exports.WorkerTypes=l,exports.availableParallelism=()=>{let e=1;try{e=k.availableParallelism()}catch{const t=k.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
|
|
1
|
+
"use strict";var e=require("node:cluster"),t=require("node:fs"),s=require("node:worker_threads"),r=require("node:process"),i=require("node:os"),o=require("node:crypto"),n=require("node:perf_hooks"),a=require("node:events"),u=require("node:async_hooks");function h(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var k=h(i);const d=Object.freeze({fixed:"fixed",dynamic:"dynamic"}),c=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),l=Object.freeze({thread:"thread",cluster:"cluster"}),m="default",g=Object.freeze((()=>{})),p={aggregate:!1,average:!1,median:!1},w=t=>t instanceof s.Worker?l.thread:t instanceof e.Worker?l.cluster:void 0,y=t=>t instanceof s.Worker?t.threadId:t instanceof e.Worker?t.id:void 0,f=e=>Array.isArray(e)&&0===e.length?0:Array.isArray(e)&&1===e.length?e[0]:e.reduce(((e,t)=>e+t),0)/e.length,T=e=>{if(Array.isArray(e)&&0===e.length)return 0;if(Array.isArray(e)&&1===e.length)return e[0];const t=e.slice().sort(((e,t)=>e-t));return(t[t.length-1>>1]+t[t.length>>1])/2},N=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},W=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),S=(e,t)=>t===e,x=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,v=()=>o.getRandomValues(new Uint32Array(1))[0]/4294967296,E=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),b=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),O=(e,t)=>{var s,r;return s=t??{},t=JSON.parse(JSON.stringify(s)),null==t?.weights&&(t.weights=F(e)),{...(r=e+Object.keys(t.weights).length,{retries:r,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}}),...t}},F=(e,t)=>{t=t??I();const s={};for(let r=0;r<e;r++)s[r]=t;return s},I=()=>{const e=o.randomInt(500,2500);let t=0;for(const s of i.cpus()){null!=s.speed&&0!==s.speed||(s.speed=i.cpus().find((e=>null!=e.speed&&0!==e.speed))?.speed??e);const r=s.speed.toString().length-1;t+=1/(s.speed/Math.pow(10,r))*Math.pow(10,r)}return Math.round(t/i.cpus().length)},C=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LEAST_USED:"LEAST_USED",LEAST_BUSY:"LEAST_BUSY",LEAST_ELU:"LEAST_ELU",FAIR_SHARE:"FAIR_SHARE",WEIGHTED_ROUND_ROBIN:"WEIGHTED_ROUND_ROBIN",INTERLEAVED_WEIGHTED_ROUND_ROBIN:"INTERLEAVED_WEIGHTED_ROUND_ROBIN"}),R=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),z=e=>({size:Math.pow(e,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,tasksFinishedTimeout:2e3}),P=e=>{if(null==e)throw new TypeError("The worker file path must be specified");if("string"!=typeof e)throw new TypeError("The worker file path must be a string");if(!t.existsSync(e))throw new Error(`Cannot find the worker file '${e}'`)},M=(e,t)=>{if(null==t)throw new TypeError("Cannot instantiate a dynamic pool without specifying the maximum pool size");if(!Number.isSafeInteger(t))throw new TypeError("Cannot instantiate a dynamic pool with a non safe integer maximum pool size");if(e>t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size");if(0===t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size equal to zero");if(e===t)throw new RangeError("Cannot instantiate a dynamic pool with a minimum pool size equal to the maximum pool size. Use a fixed pool instead")},q=e=>{if(null!=e&&!Object.values(C).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},K=e=>{if(null!=e&&!W(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker node tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new RangeError(`Invalid worker node tasks concurrency: ${e.concurrency} is a negative integer or zero`);if(null!=e?.size&&!Number.isSafeInteger(e.size))throw new TypeError("Invalid worker node tasks queue size: must be an integer");if(null!=e?.size&&e.size<=0)throw new RangeError(`Invalid worker node tasks queue size: ${e.size} is a negative integer or zero`)},Q=(e,t,s)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=E(s,e.minimum??1/0),e.maximum=b(s,e.maximum??-1/0),(t.average||t.median)&&null!=s&&(e.history.push(s),t.average?e.average=f(e.history):null!=e.average&&delete e.average,t.median?e.median=T(e.history):null!=e.median&&delete e.median))};"test"===r.env.NODE_ENV&&(exports.updateMeasurementStatistics=Q);const U=(e,t,s)=>{const r=performance.now(),i=r-(s.timestamp??r);Q(t.waitTime,e.getTaskStatisticsRequirements().waitTime,i)},A=(e,t)=>{const s=e.tasks;null!=s.executing&&s.executing>0&&--s.executing,null==t.workerError?++s.executed:++s.failed},B=(e,t,s)=>{null==s.workerError&&Q(t.runTime,e.getTaskStatisticsRequirements().runTime,s.taskPerformance?.runTime??0)},D=(e,t,s)=>{if(null!=s.workerError)return;const r=e.getTaskStatisticsRequirements().elu;Q(t.elu.active,r,s.taskPerformance?.elu?.active??0),Q(t.elu.idle,r,s.taskPerformance?.elu?.idle??0),r.aggregate&&null!=s.taskPerformance?.elu&&(null!=t.elu.utilization?t.elu.utilization=(t.elu.utilization+s.taskPerformance.elu.utilization)/2:t.elu.utilization=s.taskPerformance.elu.utilization)},L=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class H{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:p,waitTime:p,elu:p};constructor(e,t){this.pool=e,this.opts=t,this.opts=O(this.pool.info.maxSize,this.opts),this.setTaskStatisticsRequirements(this.opts),this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.runTime,e.runTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.waitTime,e.waitTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.elu,e.elu?.median)}toggleMedianMeasurementStatisticsRequirements(e,t){e.average&&t&&(e.average=!1,e.median=t),e.median&&!t&&(e.average=!0,e.median=t)}resetWorkerNodeKeyProperties(){this.nextWorkerNodeKey=0,this.previousWorkerNodeKey=0}setOptions(e){this.opts=O(this.pool.info.maxSize,e),this.setTaskStatisticsRequirements(this.opts)}hasPoolWorkerNodesReady(){return this.pool.workerNodes.some((e=>e.info.ready))}isWorkerNodeReady(e){return this.pool.workerNodes[e]?.info?.ready??!1}checkNextWorkerNodeReadiness(){this.isWorkerNodeReady(this.nextWorkerNodeKey)||delete this.nextWorkerNodeKey}getWorkerNodeTaskRunTime(e){return this.taskStatisticsRequirements.runTime.median?this.pool.workerNodes[e].usage.runTime.median??0:this.pool.workerNodes[e].usage.runTime.average??0}getWorkerNodeTaskWaitTime(e){return this.taskStatisticsRequirements.waitTime.median?this.pool.workerNodes[e].usage.waitTime.median??0:this.pool.workerNodes[e].usage.waitTime.average??0}getWorkerNodeTaskElu(e){return this.taskStatisticsRequirements.elu.median?this.pool.workerNodes[e].usage.elu.active.median??0:this.pool.workerNodes[e].usage.elu.active.average??0}setPreviousWorkerNodeKey(e){this.previousWorkerNodeKey=e??this.previousWorkerNodeKey}}class j extends H{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:{aggregate:!0,average:!0,median:!1}};constructor(e,t){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){for(const e of this.pool.workerNodes)delete e.strategyData?.virtualTaskEndTimestamp;return!0}update(e){return this.pool.workerNodes[e].strategyData={virtualTaskEndTimestamp:this.computeWorkerNodeVirtualTaskEndTimestamp(e)},!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.fairShareNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}fairShareNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>(null==t.strategyData?.virtualTaskEndTimestamp&&(t.strategyData={virtualTaskEndTimestamp:this.computeWorkerNodeVirtualTaskEndTimestamp(s)}),this.isWorkerNodeReady(s)&&t.strategyData.virtualTaskEndTimestamp<r[e].strategyData.virtualTaskEndTimestamp?s:e)),0)}computeWorkerNodeVirtualTaskEndTimestamp(e){return this.getWorkerNodeVirtualTaskEndTimestamp(e,this.getWorkerNodeVirtualTaskStartTimestamp(e))}getWorkerNodeVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===R.elu?this.getWorkerNodeTaskElu(e):this.getWorkerNodeTaskRunTime(e))}getWorkerNodeVirtualTaskStartTimestamp(e){const t=this.pool.workerNodes[e]?.strategyData?.virtualTaskEndTimestamp,s=performance.now();return s<(t??-1/0)?t:s}}class _ extends H{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};roundId=0;roundWeights;workerNodeId=0;workerNodeVirtualTaskRunTime=0;constructor(e,t){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,this.workerNodeId=0,this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){for(let e=this.roundId;e<this.roundWeights.length;e++){this.roundId=e;for(let t=this.workerNodeId;t<this.pool.workerNodes.length;t++){this.workerNodeId=t,this.workerNodeId!==this.nextWorkerNodeKey&&0!==this.workerNodeVirtualTaskRunTime&&(this.workerNodeVirtualTaskRunTime=0);const s=this.opts.weights?.[t];if(this.isWorkerNodeReady(t)&&s>=this.roundWeights[e]&&this.workerNodeVirtualTaskRunTime<s)return this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(t),this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=t,this.nextWorkerNodeKey}}this.interleavedWeightedRoundRobinNextWorkerNodeId()}interleavedWeightedRoundRobinNextWorkerNodeId(){this.roundId===this.roundWeights.length-1&&this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=0,this.workerNodeId=0):this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=this.roundId+1,this.workerNodeId=0):this.workerNodeId=this.workerNodeId+1}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.workerNodeId===e&&this.workerNodeId>this.pool.workerNodes.length-1&&(this.workerNodeId=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}setOptions(e){super.setOptions(e),this.roundWeights=this.getRoundWeights()}getRoundWeights(){return[...new Set(Object.values(this.opts.weights).slice().sort(((e,t)=>e-t)))]}}class V extends H{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:p};constructor(e,t){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastBusyNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastBusyNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>this.isWorkerNodeReady(s)&&(t.usage.runTime.aggregate??0)+(t.usage.waitTime.aggregate??0)<(r[e].usage.runTime.aggregate??0)+(r[e].usage.waitTime.aggregate??0)?s:e),0)}}class $ extends H{constructor(e,t){super(e,t)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>this.isWorkerNodeReady(s)&&t.usage.tasks.executed+t.usage.tasks.executing+t.usage.tasks.queued<r[e].usage.tasks.executed+r[e].usage.tasks.executing+r[e].usage.tasks.queued?s:e),0)}}class G extends H{taskStatisticsRequirements={runTime:p,waitTime:p,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastEluNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastEluNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>this.isWorkerNodeReady(s)&&(t.usage.elu.active.aggregate??0)<(r[e].usage.elu.active.aggregate??0)?s:e),0)}}class Y extends H{constructor(e,t){super(e,t)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.setPreviousWorkerNodeKey(e),this.roundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeReadiness(),e}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}roundRobinNextWorkerNodeKey(){return this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.nextWorkerNodeKey}}class J extends H{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};workerNodeVirtualTaskRunTime=0;constructor(e,t){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.weightedRoundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeReadiness(),this.nextWorkerNodeKey}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&(this.workerNodeVirtualTaskRunTime=0,this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey];return this.workerNodeVirtualTaskRunTime<e?this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerNodeVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class X{workerChoiceStrategy;opts;workerChoiceStrategies;constructor(e,t=C.ROUND_ROBIN,s){this.workerChoiceStrategy=t,this.opts=s,this.opts=O(e.info.maxSize,this.opts),this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[C.ROUND_ROBIN,new(Y.bind(this))(e,this.opts)],[C.LEAST_USED,new($.bind(this))(e,this.opts)],[C.LEAST_BUSY,new(V.bind(this))(e,this.opts)],[C.LEAST_ELU,new(G.bind(this))(e,this.opts)],[C.FAIR_SHARE,new(j.bind(this))(e,this.opts)],[C.WEIGHTED_ROUND_ROBIN,new(J.bind(this))(e,this.opts)],[C.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(_.bind(this))(e,this.opts)]])}getStrategyPolicy(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).strategyPolicy}getTaskStatisticsRequirements(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).taskStatisticsRequirements}setWorkerChoiceStrategy(e){this.workerChoiceStrategy!==e&&(this.workerChoiceStrategy=e),this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()}update(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).update(e)}execute(){const e=this.workerChoiceStrategies.get(this.workerChoiceStrategy);return e.hasPoolWorkerNodesReady()?this.executeStrategy(e):this.execute()}executeStrategy(e){let t,s=0,r=0;do{t=e.choose(),null==t&&s>0&&r++,s++}while(null==t&&r<this.opts?.retries);if(null==t)throw new Error(`Worker node key chosen is null or undefined after ${r} retries`);return t}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e,t){this.opts=O(e.info.maxSize,t);for(const e of this.workerChoiceStrategies.values())e.setOptions(this.opts)}}class Z extends Array{size;constructor(e=1024,...t){super(),this.checkSize(e),this.size=e,arguments.length>1&&this.push(...t)}push(...e){const t=super.push(...e);return t>this.size&&super.splice(0,t-this.size),this.length}unshift(...e){return super.unshift(...e)>this.size&&super.splice(this.size,e.length),this.length}concat(...e){const t=super.concat(e);return t.size=this.size,t.length>t.size&&t.splice(0,t.length-t.size),t}splice(e,t,...s){let r=[];if(arguments.length>=3&&null!=t){if(r=super.splice(e,t,...s),this.length>this.size){const e=super.splice(0,this.length-this.size);r=new Z(r.length+e.length,...r,...e)}}else r=2===arguments.length?super.splice(e,t):super.splice(e);return r}resize(e){if(this.checkSize(e),0===e)this.length=0;else if(e<this.size)for(let t=e;t<this.size;t++)super.pop();this.size=e}empty(){return 0===this.length}full(){return this.length===this.size}checkSize(e){if(!Number.isSafeInteger(e))throw new TypeError(`Invalid circular array size: ${e} is not a safe integer`);if(e<0)throw new RangeError(`Invalid circular array size: ${e} < 0`)}}class ee{data;next;prev;constructor(e){this.data=e}}class te{head;tail;size;maxSize;constructor(){this.clear()}push(e){const t=new ee(e);return null==this.tail?this.head=this.tail=t:(t.prev=this.tail,this.tail=this.tail.next=t),this.incrementSize()}unshift(e){const t=new ee(e);return null==this.head?this.head=this.tail=t:(t.next=this.head,this.head=this.head.prev=t),this.incrementSize()}pop(){if(null==this.head)return;const e=this.tail;return this.tail=this.tail.prev,null==this.tail?delete this.head:delete this.tail.next,--this.size,e?.data}shift(){if(null==this.head)return;const e=this.head;return this.head=this.head.next,null==this.head?delete this.tail:delete this.head.prev,--this.size,e?.data}peekFirst(){return this.head?.data}peekLast(){return this.tail?.data}clear(){delete this.head,delete this.tail,this.size=0,this.maxSize=0}[Symbol.iterator](){let e=this.head;return{next:()=>{if(null==e)return{value:void 0,done:!0};const t={value:e.data,done:!1};return e=e.next,t}}}backward(){return{[Symbol.iterator]:()=>{let e=this.tail;return{next:()=>{if(null==e)return{value:void 0,done:!0};const t={value:e.data,done:!1};return e=e.prev,t}}}}}incrementSize(){return++this.size,this.size>this.maxSize&&(this.maxSize=this.size),this.size}}class se extends a.EventEmitter{worker;info;usage;strategyData;messageChannel;tasksQueueBackPressureSize;tasksQueue;onBackPressureStarted;taskFunctionsUsage;constructor(t,r,i){super(),((e,t,s)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker type");if(!Object.values(l).includes(e))throw new TypeError(`Cannot construct a worker node with an invalid worker type '${e}'`);if(P(t),null==s)throw new TypeError("Cannot construct a worker node without worker node options");if(!W(s))throw new TypeError("Cannot construct a worker node with invalid options: must be a plain object");if(null==s.tasksQueueBackPressureSize)throw new TypeError("Cannot construct a worker node without a tasks queue back pressure size option");if(!Number.isSafeInteger(s.tasksQueueBackPressureSize))throw new TypeError("Cannot construct a worker node with a tasks queue back pressure size option that is not an integer");if(s.tasksQueueBackPressureSize<=0)throw new RangeError("Cannot construct a worker node with a tasks queue back pressure size option that is not a positive integer")})(t,r,i),this.worker=((t,r,i)=>{switch(t){case l.thread:return new s.Worker(r,{env:s.SHARE_ENV,...i?.workerOptions});case l.cluster:return e.fork(i?.env);default:throw new Error(`Unknown worker type '${t}'`)}})(t,r,{env:i.env,workerOptions:i.workerOptions}),this.info=this.initWorkerInfo(this.worker),this.usage=this.initWorkerUsage(),this.info.type===l.thread&&(this.messageChannel=new s.MessageChannel),this.tasksQueueBackPressureSize=i.tasksQueueBackPressureSize,this.tasksQueue=new te,this.onBackPressureStarted=!1,this.taskFunctionsUsage=new Map}tasksQueueSize(){return this.tasksQueue.size}enqueueTask(e){const t=this.tasksQueue.push(e);return this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.emit("backPressure",{workerId:this.info.id}),this.onBackPressureStarted=!1),t}unshiftTask(e){const t=this.tasksQueue.unshift(e);return this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.emit("backPressure",{workerId:this.info.id}),this.onBackPressureStarted=!1),t}dequeueTask(){return this.tasksQueue.shift()}popTask(){return this.tasksQueue.pop()}clearTasksQueue(){this.tasksQueue.clear()}hasBackPressure(){return this.tasksQueue.size>=this.tasksQueueBackPressureSize}resetUsage(){this.usage=this.initWorkerUsage(),this.taskFunctionsUsage.clear()}async terminate(){const e=new Promise((e=>{this.registerOnceWorkerEventHandler("exit",(()=>{e()}))}));this.closeMessageChannel(),this.removeAllListeners(),this.info.type===l.thread?await(this.worker.terminate?.()):this.info.type===l.cluster&&(this.registerOnceWorkerEventHandler("disconnect",(()=>{this.worker.kill?.()})),this.worker.disconnect?.()),await e}registerWorkerEventHandler(e,t){this.worker.on(e,t)}registerOnceWorkerEventHandler(e,t){this.worker.once(e,t)}getTaskFunctionWorkerUsage(e){if(!Array.isArray(this.info.taskFunctionNames))throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list is not yet defined`);if(Array.isArray(this.info.taskFunctionNames)&&this.info.taskFunctionNames.length<3)throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list has less than 3 elements`);return e===m&&(e=this.info.taskFunctionNames[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}deleteTaskFunctionWorkerUsage(e){return this.taskFunctionsUsage.delete(e)}closeMessageChannel(){null!=this.messageChannel&&(this.messageChannel.port1.unref(),this.messageChannel.port2.unref(),this.messageChannel.port1.close(),this.messageChannel.port2.close(),delete this.messageChannel)}initWorkerInfo(e){return{id:y(e),type:w(e),dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueue.size,t=()=>this.tasksQueue.maxSize;return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},sequentiallyStolen:0,stolen:0,failed:0},runTime:{history:new Z},waitTime:{history:new Z},elu:{idle:{history:new Z},active:{history:new Z}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===m&&e===this.info.taskFunctionNames[1]||s.name!==m&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},sequentiallyStolen:0,stolen:0,failed:0},runTime:{history:new Z},waitTime:{history:new Z},elu:{idle:{history:new Z},active:{history:new Z}}}}}class re{minimumNumberOfWorkers;filePath;opts;maximumNumberOfWorkers;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;taskFunctions;started;starting;destroying;readyEventEmitted;startTimestamp;constructor(e,t,s,r){if(this.minimumNumberOfWorkers=e,this.filePath=t,this.opts=s,this.maximumNumberOfWorkers=r,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");this.checkPoolType(),P(this.filePath),this.checkMinimumNumberOfWorkers(this.minimumNumberOfWorkers),this.checkPoolOptions(this.opts),this.chooseWorkerNode=this.chooseWorkerNode.bind(this),this.executeTask=this.executeTask.bind(this),this.enqueueTask=this.enqueueTask.bind(this),!0===this.opts.enableEvents&&this.initializeEventEmitter(),this.workerChoiceStrategyContext=new X(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.taskFunctions=new Map,this.started=!1,this.starting=!1,this.destroying=!1,this.readyEventEmitted=!1,!0===this.opts.startWorkers&&this.start(),this.startTimestamp=n.performance.now()}checkPoolType(){if(this.type===d.fixed&&null!=this.maximumNumberOfWorkers)throw new Error("Cannot instantiate a fixed pool with a maximum number of workers specified at initialization")}checkMinimumNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new TypeError("Cannot instantiate a pool with a non safe integer number of workers");if(e<0)throw new RangeError("Cannot instantiate a pool with a negative number of workers");if(this.type===d.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkPoolOptions(e){if(!W(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.startWorkers=e.startWorkers??!0,q(e.workerChoiceStrategy),this.opts.workerChoiceStrategy=e.workerChoiceStrategy??C.ROUND_ROBIN,this.checkValidWorkerChoiceStrategyOptions(e.workerChoiceStrategyOptions),null!=e.workerChoiceStrategyOptions&&(this.opts.workerChoiceStrategyOptions=e.workerChoiceStrategyOptions),this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(K(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategyOptions(e){if(null!=e&&!W(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e?.weights&&Object.keys(e.weights).length!==(this.maximumNumberOfWorkers??this.minimumNumberOfWorkers))throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e?.measurement&&!Object.values(R).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}initializeEventEmitter(){this.emitter=new a.EventEmitterAsyncResource({name:`poolifier:${this.type}-${this.worker}-pool`})}get info(){return{version:"3.1.8",type:this.type,worker:this.worker,started:this.started,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minimumNumberOfWorkers,maxSize:this.maximumNumberOfWorkers??this.minimumNumberOfWorkers,...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:N(this.utilization)},workerNodes:this.workerNodes.length,idleWorkerNodes:this.workerNodes.reduce(((e,t)=>0===t.usage.tasks.executing?e+1:e),0),busyWorkerNodes:this.workerNodes.reduce(((e,t,s)=>this.isWorkerNodeBusy(s)?e+1:e),0),executedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executed),0),executingTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executing),0),...!0===this.opts.enableTasksQueue&&{queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0)},...!0===this.opts.enableTasksQueue&&{maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.maxQueued??0)),0)},...!0===this.opts.enableTasksQueue&&{backPressure:this.hasBackPressure()},...!0===this.opts.enableTasksQueue&&{stolenTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.stolen),0)},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:N(E(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:N(b(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime.average&&{average:N(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime.median&&{median:N(T(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:N(E(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:N(b(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.average&&{average:N(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.median&&{median:N(T(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minimumNumberOfWorkers}get utilization(){const e=(n.performance.now()-this.startTimestamp)*(this.maximumNumberOfWorkers??this.minimumNumberOfWorkers);return(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)+this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0))/e}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Worker message received without worker id");if(-1===this.getWorkerNodeKeyByWorkerId(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKeyByWorkerId(e){return this.workerNodes.findIndex((t=>t.info.id===e))}setWorkerChoiceStrategy(e,t){q(e),this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(this.opts.workerChoiceStrategy),null!=t&&this.setWorkerChoiceStrategyOptions(t);for(const[e,t]of this.workerNodes.entries())t.resetUsage(),this.sendStatisticsMessageToWorker(e)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),null!=e&&(this.opts.workerChoiceStrategyOptions=e),this.workerChoiceStrategyContext.setOptions(this,this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||(this.unsetTaskStealing(),this.unsetTasksStealingOnBackPressure(),this.flushTasksQueues()),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(K(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e),this.setTasksQueueSize(this.opts.tasksQueueOptions.size),!0===this.opts.tasksQueueOptions.taskStealing?(this.unsetTaskStealing(),this.setTaskStealing()):this.unsetTaskStealing(),!0===this.opts.tasksQueueOptions.tasksStealingOnBackPressure?(this.unsetTasksStealingOnBackPressure(),this.setTasksStealingOnBackPressure()):this.unsetTasksStealingOnBackPressure()):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{...z(this.maximumNumberOfWorkers??this.minimumNumberOfWorkers),...e}}setTasksQueueSize(e){for(const t of this.workerNodes)t.tasksQueueBackPressureSize=e}setTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].on("idleWorkerNode",this.handleIdleWorkerNodeEvent)}unsetTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].off("idleWorkerNode",this.handleIdleWorkerNodeEvent)}setTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].on("backPressure",this.handleBackPressureEvent)}unsetTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].off("backPressure",this.handleBackPressureEvent)}get full(){return this.workerNodes.length>=(this.maximumNumberOfWorkers??this.minimumNumberOfWorkers)}internalBusy(){return!0===this.opts.enableTasksQueue?-1===this.workerNodes.findIndex((e=>e.info.ready&&e.usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency)):-1===this.workerNodes.findIndex((e=>e.info.ready&&0===e.usage.tasks.executing))}isWorkerNodeBusy(e){return!0===this.opts.enableTasksQueue?this.workerNodes[e].usage.tasks.executing>=this.opts.tasksQueueOptions?.concurrency:this.workerNodes[e].usage.tasks.executing>0}async sendTaskFunctionOperationToWorker(e,t){return await new Promise(((s,r)=>{const i=t=>{this.checkMessageWorkerId(t);const o=this.getWorkerInfo(e).id;null!=t.taskFunctionOperationStatus&&t.workerId===o&&(t.taskFunctionOperationStatus?s(!0):t.taskFunctionOperationStatus||r(new Error(`Task function operation '${t.taskFunctionOperation}' failed on worker ${t.workerId} with error: '${t.workerError?.message}'`)),this.deregisterWorkerMessageListener(this.getWorkerNodeKeyByWorkerId(t.workerId),i))};this.registerWorkerMessageListener(e,i),this.sendToWorker(e,t)}))}async sendTaskFunctionOperationToWorkers(e){return await new Promise(((t,s)=>{const r=new Array,i=e=>{if(this.checkMessageWorkerId(e),null!=e.taskFunctionOperationStatus&&(r.push(e),r.length===this.workerNodes.length)){if(r.every((e=>!0===e.taskFunctionOperationStatus)))t(!0);else if(r.some((e=>!1===e.taskFunctionOperationStatus))){const t=r.find((e=>!1===e.taskFunctionOperationStatus));s(new Error(`Task function operation '${e.taskFunctionOperation}' failed on worker ${t?.workerId} with error: '${t?.workerError?.message}'`))}this.deregisterWorkerMessageListener(this.getWorkerNodeKeyByWorkerId(e.workerId),i)}};for(const[t]of this.workerNodes.entries())this.registerWorkerMessageListener(t,i),this.sendToWorker(t,e)}))}hasTaskFunction(e){for(const t of this.workerNodes)if(Array.isArray(t.info.taskFunctionNames)&&t.info.taskFunctionNames.includes(e))return!0;return!1}async addTaskFunction(e,t){if("string"!=typeof e)throw new TypeError("name argument must be a string");if("string"==typeof e&&0===e.trim().length)throw new TypeError("name argument must not be an empty string");if("function"!=typeof t)throw new TypeError("fn argument must be a function");const s=await this.sendTaskFunctionOperationToWorkers({taskFunctionOperation:"add",taskFunctionName:e,taskFunction:t.toString()});return this.taskFunctions.set(e,t),s}async removeTaskFunction(e){if(!this.taskFunctions.has(e))throw new Error("Cannot remove a task function not handled on the pool side");const t=await this.sendTaskFunctionOperationToWorkers({taskFunctionOperation:"remove",taskFunctionName:e});return this.deleteTaskFunctionWorkerUsages(e),this.taskFunctions.delete(e),t}listTaskFunctionNames(){for(const e of this.workerNodes)if(Array.isArray(e.info.taskFunctionNames)&&e.info.taskFunctionNames.length>0)return e.info.taskFunctionNames;return[]}async setDefaultTaskFunction(e){return await this.sendTaskFunctionOperationToWorkers({taskFunctionOperation:"default",taskFunctionName:e})}deleteTaskFunctionWorkerUsages(e){for(const t of this.workerNodes)t.deleteTaskFunctionWorkerUsage(e)}shallExecuteTask(e){return 0===this.tasksQueueSize(e)&&this.workerNodes[e].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency}async execute(e,t,s){return await new Promise(((r,i)=>{if(!this.started)return void i(new Error("Cannot execute a task on not started pool"));if(this.destroying)return void i(new Error("Cannot execute a task on destroying pool"));if(null!=t&&"string"!=typeof t)return void i(new TypeError("name argument must be a string"));if(null!=t&&"string"==typeof t&&0===t.trim().length)return void i(new TypeError("name argument must not be an empty string"));if(null!=s&&!Array.isArray(s))return void i(new TypeError("transferList argument must be an array"));const a=n.performance.now(),h=this.chooseWorkerNode(),k={name:t??m,data:e??{},transferList:s,timestamp:a,taskId:o.randomUUID()};this.promiseResponseMap.set(k.taskId,{resolve:r,reject:i,workerNodeKey:h,...null!=this.emitter&&{asyncResource:new u.AsyncResource("poolifier:task",{triggerAsyncId:this.emitter.asyncId,requireManualDestroy:!0})}}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.shallExecuteTask(h)?this.executeTask(h,k):this.enqueueTask(h,k)}))}start(){if(this.started)throw new Error("Cannot start an already started pool");if(this.starting)throw new Error("Cannot start an already starting pool");if(this.destroying)throw new Error("Cannot start a destroying pool");for(this.starting=!0;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.minimumNumberOfWorkers;)this.createAndSetupWorkerNode();this.starting=!1,this.started=!0}async destroy(){if(!this.started)throw new Error("Cannot destroy an already destroyed pool");if(this.starting)throw new Error("Cannot destroy an starting pool");if(this.destroying)throw new Error("Cannot destroy an already destroying pool");this.destroying=!0,await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(c.destroy,this.info),this.emitter?.emitDestroy(),this.emitter?.removeAllListeners(),this.readyEventEmitted=!1,this.destroying=!1,this.started=!1}async sendKillMessageToWorker(e){await new Promise(((t,s)=>{if(null==this.workerNodes?.[e])return void t();this.registerWorkerMessageListener(e,(e=>{this.checkMessageWorkerId(e),"success"===e.kill?t():"failure"===e.kill&&s(new Error(`Kill message handling failed on worker ${e.workerId}`))})),this.sendToWorker(e,{kill:!0})}))}async destroyWorkerNode(e){this.flagWorkerNodeAsNotReady(e);const t=this.flushTasksQueue(e),s=this.workerNodes[e];await(async(e,t,s,r)=>await new Promise((i=>{let o=0;0!==s?(e.on(t,(()=>{++o,o===s&&i(o)})),r>=0&&setTimeout((()=>{i(o)}),r)):i(o)})))(s,"taskFinished",t,this.opts.tasksQueueOptions?.tasksFinishedTimeout??z(this.maximumNumberOfWorkers??this.minimumNumberOfWorkers).tasksFinishedTimeout),await this.sendKillMessageToWorker(e),await s.terminate()}setupHook(){}beforeTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;++s.tasks.executing,U(this.workerChoiceStrategyContext,s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,U(this.workerChoiceStrategyContext,s,t)}}afterTaskExecutionHook(e,t){let s=!1;if(null!=this.workerNodes[e]?.usage){const r=this.workerNodes[e].usage;A(r,t),B(this.workerChoiceStrategyContext,r,t),D(this.workerChoiceStrategyContext,r,t),s=!0}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name)){const r=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name);A(r,t),B(this.workerChoiceStrategyContext,r,t),D(this.workerChoiceStrategyContext,r,t),s=!0}s&&this.workerChoiceStrategyContext.update(e)}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return null!=t&&Array.isArray(t.taskFunctionNames)&&t.taskFunctionNames.length>2}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorkerNode();if(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===d.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorkerNode();e.registerWorkerEventHandler("online",this.opts.onlineHandler??g),e.registerWorkerEventHandler("message",this.opts.messageHandler??g),e.registerWorkerEventHandler("error",this.opts.errorHandler??g),e.registerWorkerEventHandler("error",(t=>{e.info.ready=!1,this.emitter?.emit(c.error,t),!this.started||this.starting||this.destroying||!0!==this.opts.restartWorkerOnError||(e.info.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),this.started&&!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(this.workerNodes.indexOf(e)),e?.terminate().catch((e=>{this.emitter?.emit(c.error,e)}))})),e.registerWorkerEventHandler("exit",this.opts.exitHandler??g),e.registerOnceWorkerEventHandler("exit",(()=>{this.removeWorkerNode(e)}));const t=this.addWorkerNode(e);return this.afterWorkerNodeSetup(t),t}createAndSetupDynamicWorkerNode(){const e=this.createAndSetupWorkerNode();this.registerWorkerMessageListener(e,(e=>{this.checkMessageWorkerId(e);const t=this.getWorkerNodeKeyByWorkerId(e.workerId),s=this.workerNodes[t].usage;(S(L.HARD,e.kill)||S(L.SOFT,e.kill)&&(!1===this.opts.enableTasksQueue&&0===s.tasks.executing||!0===this.opts.enableTasksQueue&&0===s.tasks.executing&&0===this.tasksQueueSize(t)))&&(this.flagWorkerNodeAsNotReady(t),this.destroyWorkerNode(t).catch((e=>{this.emitter?.emit(c.error,e)})))}));const t=this.getWorkerInfo(e);if(this.sendToWorker(e,{checkActive:!0}),this.taskFunctions.size>0)for(const[t,s]of this.taskFunctions)this.sendTaskFunctionOperationToWorker(e,{taskFunctionOperation:"add",taskFunctionName:t,taskFunction:s.toString()}).catch((e=>{this.emitter?.emit(c.error,e)}));return t.dynamic=!0,(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerReady||this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)&&(t.ready=!0),this.checkAndEmitDynamicWorkerCreationEvents(),e}afterWorkerNodeSetup(e){this.registerWorkerMessageListener(e,this.workerMessageListener),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e),!0===this.opts.enableTasksQueue&&(!0===this.opts.tasksQueueOptions?.taskStealing&&this.workerNodes[e].on("idleWorkerNode",this.handleIdleWorkerNodeEvent),!0===this.opts.tasksQueueOptions?.tasksStealingOnBackPressure&&this.workerNodes[e].on("backPressure",this.handleBackPressureEvent))}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate}})}handleTask(e,t){this.shallExecuteTask(e)?this.executeTask(e,t):this.enqueueTask(e,t)}redistributeQueuedTasks(e){if(-1!==e&&!(this.workerNodes.length<=1))for(;this.tasksQueueSize(e)>0;){const t=this.workerNodes.reduce(((e,t,s,r)=>t.info.ready&&t.usage.tasks.queued<r[e].usage.tasks.queued?s:e),0);this.handleTask(t,this.dequeueTask(e))}}updateTaskStolenStatisticsWorkerUsage(e,t){const s=this.workerNodes[e];if(null!=s?.usage&&++s.usage.tasks.stolen,this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=s.getTaskFunctionWorkerUsage(t)){++s.getTaskFunctionWorkerUsage(t).tasks.stolen}}updateTaskSequentiallyStolenStatisticsWorkerUsage(e){const t=this.workerNodes[e];null!=t?.usage&&++t.usage.tasks.sequentiallyStolen}updateTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(e,t){const s=this.workerNodes[e];if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=s.getTaskFunctionWorkerUsage(t)){++s.getTaskFunctionWorkerUsage(t).tasks.sequentiallyStolen}}resetTaskSequentiallyStolenStatisticsWorkerUsage(e){const t=this.workerNodes[e];null!=t?.usage&&(t.usage.tasks.sequentiallyStolen=0)}resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(e,t){const s=this.workerNodes[e];if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=s.getTaskFunctionWorkerUsage(t)){s.getTaskFunctionWorkerUsage(t).tasks.sequentiallyStolen=0}}handleIdleWorkerNodeEvent=(e,t)=>{if(this.workerNodes.length<=1)return;const{workerNodeKey:s}=e;if(null==s)throw new Error("WorkerNode event detail workerNodeKey attribute must be defined");const r=this.workerNodes[s].usage.tasks;if(null!=t&&r.sequentiallyStolen>0&&(r.executing>0||this.tasksQueueSize(s)>0)){for(const e of this.workerNodes[s].info.taskFunctionNames)this.resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(s,e);return void this.resetTaskSequentiallyStolenStatisticsWorkerUsage(s)}const i=this.workerNodeStealTask(s);if(this.shallUpdateTaskFunctionWorkerUsage(s)&&null!=i){const e=this.workerNodes[s].getTaskFunctionWorkerUsage(i.name)?.tasks;0===e.sequentiallyStolen||null!=t&&t.name===i.name&&e.sequentiallyStolen>0?this.updateTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(s,i.name):this.resetTaskSequentiallyStolenStatisticsTaskFunctionWorkerUsage(s,i.name)}(async e=>{await new Promise((t=>{setTimeout(t,e)}))})(((e=0,t=100)=>{const s=Math.pow(2,e)*t;return s+.2*s*v()})(r.sequentiallyStolen)).then((()=>{this.handleIdleWorkerNodeEvent(e,i)})).catch(g)};workerNodeStealTask=e=>{const t=this.workerNodes.slice().sort(((e,t)=>t.usage.tasks.queued-e.usage.tasks.queued)).find(((t,s)=>t.info.ready&&s!==e&&t.usage.tasks.queued>0));if(null!=t){const s=t.popTask();return this.handleTask(e,s),this.updateTaskSequentiallyStolenStatisticsWorkerUsage(e),this.updateTaskStolenStatisticsWorkerUsage(e,s.name),s}};handleBackPressureEvent=e=>{if(this.workerNodes.length<=1)return;const{workerId:t}=e;if(this.opts.tasksQueueOptions?.size<=1)return;const s=this.workerNodes[this.getWorkerNodeKeyByWorkerId(t)],r=this.workerNodes.slice().sort(((e,t)=>e.usage.tasks.queued-t.usage.tasks.queued));for(const[e,i]of r.entries())if(s.usage.tasks.queued>0&&i.info.ready&&i.info.id!==t&&i.usage.tasks.queued<this.opts.tasksQueueOptions?.size-1){const t=s.popTask();this.handleTask(e,t),this.updateTaskStolenStatisticsWorkerUsage(e,t.name)}};workerMessageListener=e=>{this.checkMessageWorkerId(e);const{workerId:t,ready:s,taskId:r,taskFunctionNames:i}=e;null!=s&&null!=i?this.handleWorkerReadyResponse(e):null!=r?this.handleTaskExecutionResponse(e):null!=i&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(t)).taskFunctionNames=i)};handleWorkerReadyResponse(e){const{workerId:t,ready:s,taskFunctionNames:r}=e;if(!1===s)throw new Error(`Worker ${t} failed to initialize`);const i=this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(t));i.ready=s,i.taskFunctionNames=r,!this.readyEventEmitted&&this.ready&&(this.readyEventEmitted=!0,this.emitter?.emit(c.ready,this.info))}handleTaskExecutionResponse(e){const{workerId:t,taskId:s,workerError:r,data:i}=e,o=this.promiseResponseMap.get(s);if(null!=o){const{resolve:n,reject:a,workerNodeKey:u,asyncResource:h}=o,k=this.workerNodes[u];if(null!=r?(this.emitter?.emit(c.taskError,r),null!=h?h.runInAsyncScope(a,this.emitter,r.message):a(r.message)):null!=h?h.runInAsyncScope(n,this.emitter,i):n(i),h?.emitDestroy(),this.afterTaskExecutionHook(u,e),this.promiseResponseMap.delete(s),k?.emit("taskFinished",s),!0===this.opts.enableTasksQueue&&!this.destroying){const e=k.usage.tasks;this.tasksQueueSize(u)>0&&e.executing<this.opts.tasksQueueOptions?.concurrency&&this.executeTask(u,this.dequeueTask(u)),0===e.executing&&0===this.tasksQueueSize(u)&&0===e.sequentiallyStolen&&k.emit("idleWorkerNode",{workerId:t,workerNodeKey:u})}}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(c.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(c.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===d.dynamic&&this.full&&this.emitter?.emit(c.full,this.info)}getWorkerInfo(e){return this.workerNodes[e]?.info}createWorkerNode(){const e=new se(this.worker,this.filePath,{env:this.opts.env,workerOptions:this.opts.workerOptions,tasksQueueBackPressureSize:this.opts.tasksQueueOptions?.size??z(this.maximumNumberOfWorkers??this.minimumNumberOfWorkers).size});return this.starting&&(e.info.ready=!0),e}addWorkerNode(e){this.workerNodes.push(e);const t=this.workerNodes.indexOf(e);if(-1===t)throw new Error("Worker added not found in worker nodes");return t}removeWorkerNode(e){const t=this.workerNodes.indexOf(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}flagWorkerNodeAsNotReady(e){this.getWorkerInfo(e).ready=!1}hasWorkerNodeBackPressure(e){return!0===this.opts.enableTasksQueue&&this.workerNodes[e].hasBackPressure()}hasBackPressure(){return!0===this.opts.enableTasksQueue&&-1===this.workerNodes.findIndex((e=>!e.hasBackPressure()))}executeTask(e,t){this.beforeTaskExecutionHook(e,t),this.sendToWorker(e,t,t.transferList),this.checkAndEmitTaskExecutionEvents()}enqueueTask(e,t){const s=this.workerNodes[e].enqueueTask(t);return this.checkAndEmitTaskQueuingEvents(),s}dequeueTask(e){return this.workerNodes[e].dequeueTask()}tasksQueueSize(e){return this.workerNodes[e].tasksQueueSize()}flushTasksQueue(e){let t=0;for(;this.tasksQueueSize(e)>0;)this.executeTask(e,this.dequeueTask(e)),++t;return this.workerNodes[e].clearTasksQueue(),t}flushTasksQueues(){for(const[e]of this.workerNodes.entries())this.flushTasksQueue(e)}}class ie extends re{constructor(e,t,s={},r){super(e,t,s,r)}setupHook(){e.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return e.isPrimary}sendToWorker(e,t){this.workerNodes[e].worker.send({...t,workerId:this.getWorkerInfo(e).id})}sendStartupMessageToWorker(e){this.sendToWorker(e,{ready:!1})}registerWorkerMessageListener(e,t){this.workerNodes[e].worker.on("message",t)}registerOnceWorkerMessageListener(e,t){this.workerNodes[e].worker.once("message",t)}deregisterWorkerMessageListener(e,t){this.workerNodes[e].worker.off("message",t)}get type(){return d.fixed}get worker(){return l.cluster}get busy(){return this.internalBusy()}}class oe extends re{constructor(e,t,s={},r){super(e,t,s,r)}isMain(){return s.isMainThread}sendToWorker(e,t,s){this.workerNodes[e].messageChannel?.port1?.postMessage({...t,workerId:this.getWorkerInfo(e).id},s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e],s=t.messageChannel.port2;t.worker.postMessage({ready:!1,workerId:this.getWorkerInfo(e).id,port:s},[s])}registerWorkerMessageListener(e,t){this.workerNodes[e].messageChannel?.port1?.on("message",t)}registerOnceWorkerMessageListener(e,t){this.workerNodes[e].messageChannel?.port1?.once("message",t)}deregisterWorkerMessageListener(e,t){this.workerNodes[e].messageChannel?.port1?.off("message",t)}get type(){return d.fixed}get worker(){return l.thread}get busy(){return this.internalBusy()}}const ne=(e,t)=>{if("string"!=typeof e)throw new TypeError("A taskFunctions parameter object key is not a string");if("string"==typeof e&&0===e.trim().length)throw new TypeError("A taskFunctions parameter object key is an empty string");if("function"!=typeof t)throw new TypeError("A taskFunctions parameter object value is not a function")},ae=e=>{if("string"!=typeof e)throw new TypeError("name parameter is not a string");if("string"==typeof e&&0===e.trim().length)throw new TypeError("name parameter is an empty string")},ue=6e4,he={killBehavior:L.SOFT,maxInactiveTime:ue,killHandler:g};class ke{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r=he){if(this.isMain=e,this.mainWorker=t,this.opts=r,null==this.isMain)throw new Error("isMain parameter is mandatory");this.checkTaskFunctions(s),this.checkWorkerOptions(this.opts),this.isMain||this.getMainWorker().on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){(e=>{if(null!=e&&!W(e))throw new TypeError("opts worker options parameter is not a plain object");if(null!=e?.killBehavior&&!Object.values(L).includes(e.killBehavior))throw new TypeError(`killBehavior option '${e.killBehavior}' is not valid`);if(null!=e?.maxInactiveTime&&!Number.isSafeInteger(e.maxInactiveTime))throw new TypeError("maxInactiveTime option is not an integer");if(null!=e?.maxInactiveTime&&e.maxInactiveTime<5)throw new TypeError("maxInactiveTime option is not a positive integer greater or equal than 5");if(null!=e?.killHandler&&"function"!=typeof e.killHandler)throw new TypeError("killHandler option is not a function")})(e),this.opts={...he,...e}}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e){const t=e.bind(this);this.taskFunctions.set(m,t),this.taskFunctions.set("string"==typeof e.name&&e.name.trim().length>0?e.name:"fn1",t)}else{if(!W(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){ne(s,r);const e=r.bind(this);t&&(this.taskFunctions.set(m,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){try{ae(e)}catch(e){return{status:!1,error:e}}return{status:this.taskFunctions.has(e)}}addTaskFunction(e,t){try{if(ae(e),e===m)throw new Error("Cannot add a task function with the default reserved name");if("function"!=typeof t)throw new TypeError("fn parameter is not a function");const s=t.bind(this);return this.taskFunctions.get(e)===this.taskFunctions.get(m)&&this.taskFunctions.set(m,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(ae(e),e===m)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(m))throw new Error("Cannot remove the task function used as the default task function");const t=this.taskFunctions.delete(e);return this.sendTaskFunctionNamesToMainWorker(),{status:t}}catch(e){return{status:!1,error:e}}}listTaskFunctionNames(){const e=[...this.taskFunctions.keys()];let t=m;for(const[e,s]of this.taskFunctions)if(e!==m&&s===this.taskFunctions.get(m)){t=e;break}return[e[e.indexOf(m)],t,...e.filter((e=>e!==m&&e!==t))]}setDefaultTaskFunction(e){try{if(ae(e),e===m)throw new Error("Cannot set the default task function reserved name as the default task function");if(!this.taskFunctions.has(e))throw new Error("Cannot set the default task function to a non-existing task function");return this.taskFunctions.set(m,this.taskFunctions.get(e)),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskFunctionOperation?this.handleTaskFunctionOperationMessage(e):null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleTaskFunctionOperationMessage(e){const{taskFunctionOperation:t,taskFunctionName:s,taskFunction:r}=e;let i;switch(t){case"add":i=this.addTaskFunction(s,new Function(`return ${r}`)());break;case"remove":i=this.removeTaskFunction(s);break;case"default":i=this.setDefaultTaskFunction(s);break;default:i={status:!1,error:new Error("Unknown task operation")}}this.sendToMainWorker({taskFunctionOperation:t,taskFunctionOperationStatus:i.status,taskFunctionName:s,...!i.status&&null!=i?.error&&{workerError:{name:s,message:this.handleError(i.error)}}})}handleKillMessage(e){if(this.stopCheckActive(),x(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>{this.sendToMainWorker({kill:"success"})})).catch((()=>{this.sendToMainWorker({kill:"failure"})}));else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success"})}catch{this.sendToMainWorker({kill:"failure"})}}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Message worker id is not set");if(e.workerId!==this.id)throw new Error(`Message worker id ${e.workerId} does not match the worker id ${this.id}`)}startCheckActive(){this.lastTaskTimestamp=n.performance.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??ue)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){n.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??ue)&&this.sendToMainWorker({kill:this.opts.killBehavior})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}sendTaskFunctionNamesToMainWorker(){this.sendToMainWorker({taskFunctionNames:this.listTaskFunctionNames()})}handleError(e){return e instanceof Error?e.message:e}run=e=>{const{name:t,taskId:s,data:r}=e,i=t??m;if(!this.taskFunctions.has(i))return void this.sendToMainWorker({workerError:{name:t,message:`Task function '${t}' not found`,data:r},taskId:s});const o=this.taskFunctions.get(i);x(o)?this.runAsync(o,e):this.runSync(o,e)};runSync=(e,t)=>{const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,taskId:r})}catch(e){this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})}finally{this.updateLastTaskTimestamp()}};runAsync=(e,t)=>{const{name:s,taskId:r,data:i}=t;let o=this.beginTaskPerformance(s);e(i).then((e=>{o=this.endTaskPerformance(o),this.sendToMainWorker({data:e,taskPerformance:o,taskId:r})})).catch((e=>{this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(g)};beginTaskPerformance(e){return this.checkStatistics(),{name:e??m,timestamp:n.performance.now(),...this.statistics.elu&&{elu:n.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:n.performance.now()-e.timestamp},...this.statistics.elu&&{elu:n.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=n.performance.now())}}exports.ClusterWorker=class extends ke{constructor(t,s={}){super(e.isPrimary,e.worker,t,s)}handleReadyMessage(e){if(e.workerId===this.id&&!1===e.ready)try{this.getMainWorker().on("message",this.messageListener.bind(this)),this.sendToMainWorker({ready:!0,taskFunctionNames:this.listTaskFunctionNames()})}catch{this.sendToMainWorker({ready:!1,taskFunctionNames:this.listTaskFunctionNames()})}}get id(){return this.getMainWorker().id}sendToMainWorker=e=>{this.getMainWorker().send({...e,workerId:this.id})}},exports.DynamicClusterPool=class extends ie{constructor(e,t,s,r={}){super(e,s,r,t),M(this.minimumNumberOfWorkers,this.maximumNumberOfWorkers)}get type(){return d.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends oe{constructor(e,t,s,r={}){super(e,s,r,t),M(this.minimumNumberOfWorkers,this.maximumNumberOfWorkers)}get type(){return d.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=ie,exports.FixedThreadPool=oe,exports.KillBehaviors=L,exports.Measurements=R,exports.PoolEvents=c,exports.PoolTypes=d,exports.ThreadWorker=class extends ke{port;constructor(e,t={}){super(s.isMainThread,s.parentPort,e,t)}handleReadyMessage(e){if(e.workerId===this.id&&!1===e.ready&&null!=e.port)try{this.port=e.port,this.port.on("message",this.messageListener.bind(this)),this.sendToMainWorker({ready:!0,taskFunctionNames:this.listTaskFunctionNames()})}catch{this.sendToMainWorker({ready:!1,taskFunctionNames:this.listTaskFunctionNames()})}}handleKillMessage(e){super.handleKillMessage(e),this.port?.unref(),this.port?.close()}get id(){return s.threadId}sendToMainWorker=e=>{this.port?.postMessage({...e,workerId:this.id})};handleError(e){return e}},exports.WorkerChoiceStrategies=C,exports.WorkerTypes=l,exports.availableParallelism=()=>{let e=1;try{e=k.availableParallelism()}catch{const t=k.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|