poolifier 3.1.8 → 3.1.10

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 CHANGED
@@ -287,6 +287,7 @@ interface TaskFunctionOperationResult {
287
287
  /**
288
288
  * Array with a maximum length and shifting items when full.
289
289
  *
290
+ * @typeParam T - Type of items.
290
291
  * @internal
291
292
  */
292
293
  declare class CircularArray<T> extends Array<T> {
@@ -1466,7 +1467,7 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
1466
1467
  *
1467
1468
  * @returns Whether to create a dynamic worker or not.
1468
1469
  */
1469
- private shallCreateDynamicWorker;
1470
+ protected abstract shallCreateDynamicWorker(): boolean;
1470
1471
  /**
1471
1472
  * Sends a message to worker given its worker node key.
1472
1473
  *
@@ -1545,7 +1546,10 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
1545
1546
  private handleTaskExecutionResponse;
1546
1547
  private checkAndEmitTaskExecutionEvents;
1547
1548
  private checkAndEmitTaskQueuingEvents;
1548
- private checkAndEmitDynamicWorkerCreationEvents;
1549
+ /**
1550
+ * Emits dynamic worker creation events.
1551
+ */
1552
+ protected abstract checkAndEmitDynamicWorkerCreationEvents(): void;
1549
1553
  /**
1550
1554
  * Gets the worker information given its worker node key.
1551
1555
  *
@@ -1591,6 +1595,10 @@ declare abstract class AbstractPool<Worker extends IWorker, Data = unknown, Resp
1591
1595
  private flushTasksQueues;
1592
1596
  }
1593
1597
 
1598
+ /**
1599
+ * Options for a poolifier cluster pool.
1600
+ */
1601
+ type ClusterPoolOptions = PoolOptions<Worker>;
1594
1602
  /**
1595
1603
  * A cluster pool with a fixed number of workers.
1596
1604
  *
@@ -1607,7 +1615,7 @@ declare class FixedClusterPool<Data = unknown, Response = unknown> extends Abstr
1607
1615
  * @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute.
1608
1616
  * @param opts - Options for this fixed cluster pool.
1609
1617
  */
1610
- constructor(numberOfWorkers: number, filePath: string, opts?: PoolOptions<Worker>, maximumNumberOfWorkers?: number);
1618
+ constructor(numberOfWorkers: number, filePath: string, opts?: ClusterPoolOptions, maximumNumberOfWorkers?: number);
1611
1619
  /** @inheritDoc */
1612
1620
  protected setupHook(): void;
1613
1621
  /** @inheritDoc */
@@ -1623,6 +1631,10 @@ declare class FixedClusterPool<Data = unknown, Response = unknown> extends Abstr
1623
1631
  /** @inheritDoc */
1624
1632
  protected deregisterWorkerMessageListener<Message extends Data | Response>(workerNodeKey: number, listener: (message: MessageValue<Message>) => void): void;
1625
1633
  /** @inheritDoc */
1634
+ protected shallCreateDynamicWorker(): boolean;
1635
+ /** @inheritDoc */
1636
+ protected checkAndEmitDynamicWorkerCreationEvents(): void;
1637
+ /** @inheritDoc */
1626
1638
  protected get type(): PoolType;
1627
1639
  /** @inheritDoc */
1628
1640
  protected get worker(): WorkerType;
@@ -1650,13 +1662,21 @@ declare class DynamicClusterPool<Data = unknown, Response = unknown> extends Fix
1650
1662
  * @param filePath - Path to an implementation of a `ClusterWorker` file, which can be relative or absolute.
1651
1663
  * @param opts - Options for this dynamic cluster pool.
1652
1664
  */
1653
- constructor(min: number, max: number, filePath: string, opts?: PoolOptions<Worker>);
1665
+ constructor(min: number, max: number, filePath: string, opts?: ClusterPoolOptions);
1666
+ /** @inheritDoc */
1667
+ protected shallCreateDynamicWorker(): boolean;
1668
+ /** @inheritDoc */
1669
+ protected checkAndEmitDynamicWorkerCreationEvents(): void;
1654
1670
  /** @inheritDoc */
1655
1671
  protected get type(): PoolType;
1656
1672
  /** @inheritDoc */
1657
1673
  protected get busy(): boolean;
1658
1674
  }
1659
1675
 
1676
+ /**
1677
+ * Options for a poolifier thread pool.
1678
+ */
1679
+ type ThreadPoolOptions = PoolOptions<Worker$1>;
1660
1680
  /**
1661
1681
  * A thread pool with a fixed number of threads.
1662
1682
  *
@@ -1673,7 +1693,7 @@ declare class FixedThreadPool<Data = unknown, Response = unknown> extends Abstra
1673
1693
  * @param filePath - Path to an implementation of a `ThreadWorker` file, which can be relative or absolute.
1674
1694
  * @param opts - Options for this fixed thread pool.
1675
1695
  */
1676
- constructor(numberOfThreads: number, filePath: string, opts?: PoolOptions<Worker$1>, maximumNumberOfThreads?: number);
1696
+ constructor(numberOfThreads: number, filePath: string, opts?: ThreadPoolOptions, maximumNumberOfThreads?: number);
1677
1697
  /** @inheritDoc */
1678
1698
  protected isMain(): boolean;
1679
1699
  /** @inheritDoc */
@@ -1687,6 +1707,10 @@ declare class FixedThreadPool<Data = unknown, Response = unknown> extends Abstra
1687
1707
  /** @inheritDoc */
1688
1708
  protected deregisterWorkerMessageListener<Message extends Data | Response>(workerNodeKey: number, listener: (message: MessageValue<Message>) => void): void;
1689
1709
  /** @inheritDoc */
1710
+ protected shallCreateDynamicWorker(): boolean;
1711
+ /** @inheritDoc */
1712
+ protected checkAndEmitDynamicWorkerCreationEvents(): void;
1713
+ /** @inheritDoc */
1690
1714
  protected get type(): PoolType;
1691
1715
  /** @inheritDoc */
1692
1716
  protected get worker(): WorkerType;
@@ -1714,7 +1738,11 @@ declare class DynamicThreadPool<Data = unknown, Response = unknown> extends Fixe
1714
1738
  * @param filePath - Path to an implementation of a `ThreadWorker` file, which can be relative or absolute.
1715
1739
  * @param opts - Options for this dynamic thread pool.
1716
1740
  */
1717
- constructor(min: number, max: number, filePath: string, opts?: PoolOptions<Worker$1>);
1741
+ constructor(min: number, max: number, filePath: string, opts?: ThreadPoolOptions);
1742
+ /** @inheritDoc */
1743
+ protected shallCreateDynamicWorker(): boolean;
1744
+ /** @inheritDoc */
1745
+ protected checkAndEmitDynamicWorkerCreationEvents(): void;
1718
1746
  /** @inheritDoc */
1719
1747
  protected get type(): PoolType;
1720
1748
  /** @inheritDoc */
@@ -2055,4 +2083,4 @@ declare class Deque<T> {
2055
2083
  */
2056
2084
  declare const availableParallelism: () => number;
2057
2085
 
2058
- export { AbstractPool, AbstractWorker, CircularArray, ClusterWorker, Deque, DynamicClusterPool, DynamicThreadPool, type ErrorHandler, type EventLoopUtilizationMeasurementStatistics, type ExitHandler, FixedClusterPool, FixedThreadPool, type IPool, type IWorker, type IWorkerChoiceStrategy, type IWorkerNode, type KillBehavior, KillBehaviors, type KillHandler, type Measurement, type MeasurementOptions, type MeasurementStatistics, type MeasurementStatisticsRequirements, Measurements, type MessageHandler, type MessageValue, Node, type OnlineHandler, type PoolEvent, PoolEvents, type PoolInfo, type PoolOptions, type PoolType, PoolTypes, type PromiseResponseWrapper, type StrategyData, type StrategyPolicy, type Task, type TaskAsyncFunction, type TaskFunction, type TaskFunctionOperationResult, type TaskFunctions, type TaskPerformance, type TaskStatistics, type TaskStatisticsRequirements, type TaskSyncFunction, type TasksQueueOptions, ThreadWorker, WorkerChoiceStrategies, type WorkerChoiceStrategy, WorkerChoiceStrategyContext, type WorkerChoiceStrategyOptions, type WorkerError, type WorkerInfo, type WorkerNodeEventDetail, type WorkerNodeOptions, type WorkerOptions, type WorkerStatistics, type WorkerType, WorkerTypes, type WorkerUsage, type Writable, availableParallelism };
2086
+ export { AbstractPool, AbstractWorker, CircularArray, type ClusterPoolOptions, ClusterWorker, Deque, DynamicClusterPool, DynamicThreadPool, type ErrorHandler, type EventLoopUtilizationMeasurementStatistics, type ExitHandler, FixedClusterPool, FixedThreadPool, type IPool, type IWorker, type IWorkerChoiceStrategy, type IWorkerNode, type InternalWorkerChoiceStrategyOptions, type KillBehavior, KillBehaviors, type KillHandler, type Measurement, type MeasurementOptions, type MeasurementStatistics, type MeasurementStatisticsRequirements, Measurements, type MessageHandler, type MessageValue, Node, type OnlineHandler, type PoolEvent, PoolEvents, type PoolInfo, type PoolOptions, type PoolType, PoolTypes, type PromiseResponseWrapper, type StrategyData, type StrategyPolicy, type Task, type TaskAsyncFunction, type TaskFunction, type TaskFunctionOperationResult, type TaskFunctions, type TaskPerformance, type TaskStatistics, type TaskStatisticsRequirements, type TaskSyncFunction, type TasksQueueOptions, type ThreadPoolOptions, ThreadWorker, WorkerChoiceStrategies, type WorkerChoiceStrategy, WorkerChoiceStrategyContext, type WorkerChoiceStrategyOptions, type WorkerError, type WorkerInfo, type WorkerNodeEventDetail, type WorkerNodeOptions, type WorkerOptions, type WorkerStatistics, type WorkerType, WorkerTypes, type WorkerUsage, type Writable, availableParallelism };
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"}),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};
1
+ "use strict";var e=require("node:fs"),t=require("node:cluster"),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({thread:"thread",cluster:"cluster"}),c="default",l=Object.freeze((()=>{})),m={aggregate:!1,average:!1,median:!1},g=e=>e instanceof s.Worker?d.thread:e instanceof t.Worker?d.cluster:void 0,p=e=>e instanceof s.Worker?e.threadId:e instanceof t.Worker?e.id:void 0,w=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,y=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},f=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},T=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),N=(e,t)=>t===e,W=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,S=()=>o.getRandomValues(new Uint32Array(1))[0]/4294967296,x=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),v=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),E=(e,t)=>{var s,r;return s=t??{},t=JSON.parse(JSON.stringify(s)),null==t?.weights&&(t.weights=b(e)),{...(r=e+Object.keys(t.weights).length,{retries:r,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}}),...t}},b=(e,t)=>{t=t??O();const s={};for(let r=0;r<e;r++)s[r]=t;return s},O=()=>{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)},F=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"}),I=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),C=e=>({size:Math.pow(e,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,tasksFinishedTimeout:2e3}),R=t=>{if(null==t)throw new TypeError("The worker file path must be specified");if("string"!=typeof t)throw new TypeError("The worker file path must be a string");if(!e.existsSync(t))throw new Error(`Cannot find the worker file '${t}'`)},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(F).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},M=e=>{if(null!=e&&!T(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=x(s,e.minimum??1/0),e.maximum=v(s,e.maximum??-1/0),(t.average||t.median)&&null!=s&&(e.history.push(s),t.average?e.average=w(e.history):null!=e.average&&delete e.average,t.median?e.median=y(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},A=(e,t,s)=>{null==s.workerError&&q(t.runTime,e.getTaskStatisticsRequirements().runTime,s.taskPerformance?.runTime??0)},U=(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({fixed:"fixed",dynamic:"dynamic"}),D=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),L=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class H{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:m,waitTime:m,elu:m};constructor(e,t){this.pool=e,this.opts=t,this.opts=E(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=E(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:m,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===I.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:m,elu:m};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:m};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:m,waitTime:m,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:m,elu:m};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=F.ROUND_ROBIN,s){this.workerChoiceStrategy=t,this.opts=s,this.opts=E(e.info.maxSize,this.opts),this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[F.ROUND_ROBIN,new(Y.bind(this))(e,this.opts)],[F.LEAST_USED,new($.bind(this))(e,this.opts)],[F.LEAST_BUSY,new(V.bind(this))(e,this.opts)],[F.LEAST_ELU,new(G.bind(this))(e,this.opts)],[F.FAIR_SHARE,new(j.bind(this))(e,this.opts)],[F.WEIGHTED_ROUND_ROBIN,new(J.bind(this))(e,this.opts)],[F.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=E(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(e,r,i){super(),((e,t,s)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker type");if(!Object.values(d).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(!T(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")})(e,r,i),this.worker=((e,r,i)=>{switch(e){case d.thread:return new s.Worker(r,{env:s.SHARE_ENV,...i?.workerOptions});case d.cluster:return t.fork(i?.env);default:throw new Error(`Unknown worker type '${e}'`)}})(e,r,{env:i.env,workerOptions:i.workerOptions}),this.info=this.initWorkerInfo(this.worker),this.usage=this.initWorkerUsage(),this.info.type===d.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===d.thread?await(this.worker.terminate?.()):this.info.type===d.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===c&&(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:p(e),type:g(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===c&&e===this.info.taskFunctionNames[1]||s.name!==c&&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(),R(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===B.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===B.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkPoolOptions(e){if(!T(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??F.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&&(M(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategyOptions(e){if(null!=e&&!T(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(I).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.10",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:f(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:f(x(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:f(v(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime.average&&{average:f(w(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().runTime.median&&{median:f(y(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:f(x(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:f(v(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.average&&{average:f(w(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext?.getTaskStatisticsRequirements().waitTime.median&&{median:f(y(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){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),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?(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.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??c,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(D.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??C(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,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),A(this.workerChoiceStrategyContext,r,t),U(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),A(this.workerChoiceStrategyContext,r,t),U(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()}createAndSetupWorkerNode(){const e=this.createWorkerNode();e.registerWorkerEventHandler("online",this.opts.onlineHandler??l),e.registerWorkerEventHandler("message",this.opts.messageHandler??l),e.registerWorkerEventHandler("error",this.opts.errorHandler??l),e.registerWorkerEventHandler("error",(t=>{e.info.ready=!1,this.emitter?.emit(D.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(D.error,e)}))})),e.registerWorkerEventHandler("exit",this.opts.exitHandler??l),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;(N(L.HARD,e.kill)||N(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(D.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(D.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*S()})(r.sequentiallyStolen)).then((()=>{this.handleIdleWorkerNodeEvent(e,i)})).catch(l)};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(D.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(D.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(D.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(D.backPressure,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??C(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(){t.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return t.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)}shallCreateDynamicWorker(){return!1}checkAndEmitDynamicWorkerCreationEvents(){}get type(){return B.fixed}get worker(){return d.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)}shallCreateDynamicWorker(){return!1}checkAndEmitDynamicWorkerCreationEvents(){}get type(){return B.fixed}get worker(){return d.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:l};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&&!T(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(c,t),this.taskFunctions.set("string"==typeof e.name&&e.name.trim().length>0?e.name:"fn1",t)}else{if(!T(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(c,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===c)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(c)&&this.taskFunctions.set(c,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(ae(e),e===c)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(c))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=c;for(const[e,s]of this.taskFunctions)if(e!==c&&s===this.taskFunctions.get(c)){t=e;break}return[e[e.indexOf(c)],t,...e.filter((e=>e!==c&&e!==t))]}setDefaultTaskFunction(e){try{if(ae(e),e===c)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(c,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(),W(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??c;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);W(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(l)};beginTaskPerformance(e){return this.checkStatistics(),{name:e??c,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(e,s={}){super(t.isPrimary,t.worker,e,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),z(this.minimumNumberOfWorkers,this.maximumNumberOfWorkers)}shallCreateDynamicWorker(){return!this.full&&this.internalBusy()}checkAndEmitDynamicWorkerCreationEvents(){this.full&&this.emitter?.emit(D.full,this.info)}get type(){return B.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends oe{constructor(e,t,s,r={}){super(e,s,r,t),z(this.minimumNumberOfWorkers,this.maximumNumberOfWorkers)}shallCreateDynamicWorker(){return!this.full&&this.internalBusy()}checkAndEmitDynamicWorkerCreationEvents(){this.full&&this.emitter?.emit(D.full,this.info)}get type(){return B.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=ie,exports.FixedThreadPool=oe,exports.KillBehaviors=L,exports.Measurements=I,exports.PoolEvents=D,exports.PoolTypes=B,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=F,exports.WorkerTypes=d,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