Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

poolifier

Package Overview
Dependencies
Maintainers
1
Versions
192
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

poolifier - npm Package Compare versions

Comparing version 2.7.2 to 2.7.3

2

./lib/index.js

@@ -1,2 +0,2 @@

"use strict";var e=require("node:events"),t=require("node:fs"),s=require("node:os"),r=require("node:crypto"),i=require("node:cluster"),o=require("node:worker_threads"),n=require("node:perf_hooks"),a=require("node:async_hooks");function u(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 h=u(s);const k=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class c extends e.EventEmitter{}const d=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),l=Object.freeze({thread:"thread",cluster:"cluster"}),g="default",m=Object.freeze((()=>{})),p={retries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},w={aggregate:!1,average:!1,median:!1},y=e=>e instanceof o.Worker?l.thread:e instanceof i.Worker?l.cluster:void 0,T=e=>e instanceof o.Worker?e.threadId:e instanceof i.Worker?e.id:void 0,f=e=>Array.isArray(e)&&0===e.length?0:Array.isArray(e)&&1===e.length?e[0]:e.reduce(((e,t)=>e+t),0)/e.length,N=e=>{if(Array.isArray(e)&&0===e.length)return 0;if(Array.isArray(e)&&1===e.length)return e[0];const t=e.slice().sort(((e,t)=>e-t));return(t[t.length-1>>1]+t[t.length>>1])/2},W=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},S=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),x=(e,t)=>t===e,E=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,v=()=>r.webcrypto.getRandomValues(new Uint32Array(1))[0]/4294967296,b=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),I=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),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"}),O=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),F=(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")},R=e=>{if(null!=e&&!Object.values(C).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},z=e=>{if(null!=e&&!S(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker node tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new RangeError(`Invalid worker node tasks concurrency: ${e.concurrency} is a negative integer or zero`);if(null!=e?.size&&!Number.isSafeInteger(e.size))throw new TypeError("Invalid worker node tasks queue size: must be an integer");if(null!=e?.size&&e.size<=0)throw new RangeError(`Invalid worker node tasks queue size: ${e.size} is a negative integer or zero`)},P=(e,t,s)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=b(s,e.minimum??1/0),e.maximum=I(s,e.maximum??-1/0),(t.average||t.median)&&null!=s&&(e.history.push(s),t.average?e.average=f(e.history):null!=e.average&&delete e.average,t.median?e.median=N(e.history):null!=e.median&&delete e.median))},M=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class Q{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:w,waitTime:w,elu:w};constructor(e,t=p){this.pool=e,this.opts=t,this.opts={...p,...t},this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.runTime,e.runTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.waitTime,e.waitTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.elu,e.elu?.median)}toggleMedianMeasurementStatisticsRequirements(e,t){e.average&&t&&(e.average=!1,e.median=t),e.median&&!t&&(e.average=!0,e.median=t)}resetWorkerNodeKeyProperties(){this.nextWorkerNodeKey=0,this.previousWorkerNodeKey=0}setOptions(e){this.opts={...p,...e},this.setTaskStatisticsRequirements(this.opts)}isWorkerNodeReady(e){return this.pool.workerNodes[e].info.ready}hasWorkerNodeBackPressure(e){return this.pool.hasWorkerNodeBackPressure(e)}isWorkerNodeEligible(e){return this.isWorkerNodeReady(e)&&!this.hasWorkerNodeBackPressure(e)}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}checkNextWorkerNodeEligibility(){this.isWorkerNodeEligible(this.nextWorkerNodeKey)||(this.nextWorkerNodeKey=void 0)}computeDefaultWorkerWeight(){let e=0;for(const t of s.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/s.cpus().length)}}class K extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:w,elu:{aggregate:!0,average:!0,median:!1}};constructor(e,t=p){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)}),t.strategyData.virtualTaskEndTimestamp<r[e].strategyData.virtualTaskEndTimestamp?s:e)),0)}computeWorkerNodeVirtualTaskEndTimestamp(e){return this.getWorkerNodeVirtualTaskEndTimestamp(e,this.getWorkerNodeVirtualTaskStartTimestamp(e))}getWorkerNodeVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===O.elu?this.getWorkerNodeTaskElu(e):this.getWorkerNodeTaskRunTime(e))}getWorkerNodeVirtualTaskStartTimestamp(e){const t=this.pool.workerNodes[e]?.strategyData?.virtualTaskEndTimestamp,s=performance.now();return s<(t??-1/0)?t:s}}class q extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:w,elu:w};roundId=0;defaultWorkerWeight;roundWeights;workerNodeId=0;workerNodeVirtualTaskRunTime=0;constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,this.workerNodeId=0,this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){for(let e=this.roundId;e<this.roundWeights.length;e++){this.roundId=e;for(let t=this.workerNodeId;t<this.pool.workerNodes.length;t++){this.workerNodeId=t,this.workerNodeId!==this.nextWorkerNodeKey&&0!==this.workerNodeVirtualTaskRunTime&&(this.workerNodeVirtualTaskRunTime=0);const s=this.opts.weights?.[t]??this.defaultWorkerWeight;if(s>=this.roundWeights[e]&&this.workerNodeVirtualTaskRunTime<s)return this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(t),this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=t,this.nextWorkerNodeKey}}this.interleavedWeightedRoundRobinNextWorkerNodeId()}interleavedWeightedRoundRobinNextWorkerNodeId(){this.roundId===this.roundWeights.length-1&&this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=0,this.workerNodeId=0):this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=this.roundId+1,this.workerNodeId=0):this.workerNodeId=this.workerNodeId+1}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.workerNodeId===e&&this.workerNodeId>this.pool.workerNodes.length-1&&(this.workerNodeId=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}setOptions(e){super.setOptions(e),this.roundWeights=this.getRoundWeights()}getRoundWeights(){return null==this.opts.weights?[this.defaultWorkerWeight]:[...new Set(Object.values(this.opts.weights).slice().sort(((e,t)=>e-t)))]}}class B extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:w};constructor(e,t=p){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)=>(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 U extends Q{constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>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 A extends Q{taskStatisticsRequirements={runTime:w,waitTime:w,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=p){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)=>(t.usage.elu.active.aggregate??0)<(r[e].usage.elu.active.aggregate??0)?s:e),0)}}class D extends Q{constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.setPreviousWorkerNodeKey(e),this.roundRobinNextWorkerNodeKey(),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 L extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:w,elu:w};defaultWorkerWeight;workerNodeVirtualTaskRunTime=0;constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.weightedRoundRobinNextWorkerNodeKey()}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&(this.workerNodeVirtualTaskRunTime=0,this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight;return this.workerNodeVirtualTaskRunTime<e?this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerNodeVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class _{workerChoiceStrategy;opts;workerChoiceStrategies;retriesCount=0;constructor(e,t=C.ROUND_ROBIN,s=p){this.workerChoiceStrategy=t,this.opts=s,this.opts={...p,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[C.ROUND_ROBIN,new(D.bind(this))(e,s)],[C.LEAST_USED,new(U.bind(this))(e,s)],[C.LEAST_BUSY,new(B.bind(this))(e,s)],[C.LEAST_ELU,new(A.bind(this))(e,s)],[C.FAIR_SHARE,new(K.bind(this))(e,s)],[C.WEIGHTED_ROUND_ROBIN,new(L.bind(this))(e,s)],[C.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(q.bind(this))(e,s)]])}getStrategyPolicy(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).strategyPolicy}getTaskStatisticsRequirements(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).taskStatisticsRequirements}setWorkerChoiceStrategy(e){this.workerChoiceStrategy!==e&&(this.workerChoiceStrategy=e),this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()}update(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).update(e)}execute(){const e=this.workerChoiceStrategies.get(this.workerChoiceStrategy).choose();if(null==e&&this.retriesCount<this.opts.retries)return this.retriesCount++,this.execute();if(null==e)throw new Error(`Worker node key chosen is null or undefined after ${this.retriesCount} retries`);return this.retriesCount=0,e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...p,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class j extends Array{size;constructor(e=1024,...t){super(),this.checkSize(e),this.size=e,arguments.length>1&&this.push(...t)}push(...e){const t=super.push(...e);return t>this.size&&super.splice(0,t-this.size),this.length}unshift(...e){return super.unshift(...e)>this.size&&super.splice(this.size,e.length),this.length}concat(...e){const t=super.concat(e);return t.size=this.size,t.length>t.size&&t.splice(0,t.length-t.size),t}splice(e,t,...s){let r=[];if(arguments.length>=3&&null!=t){if(r=super.splice(e,t,...s),this.length>this.size){const e=super.splice(0,this.length-this.size);r=new j(r.length+e.length,...r,...e)}}else r=2===arguments.length?super.splice(e,t):super.splice(e);return r}resize(e){if(this.checkSize(e),0===e)this.length=0;else if(e<this.size)for(let t=e;t<this.size;t++)super.pop();this.size=e}empty(){return 0===this.length}full(){return this.length===this.size}checkSize(e){if(!Number.isSafeInteger(e))throw new TypeError(`Invalid circular array size: ${e} is not a safe integer`);if(e<0)throw new RangeError(`Invalid circular array size: ${e} < 0`)}}class H{data;next;prev;constructor(e){this.data=e}}class V{head;tail;size;maxSize;constructor(){this.clear()}push(e){const t=new H(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 H(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?this.head=void 0:this.tail.next=void 0,--this.size,e?.data}shift(){if(null==this.head)return;const e=this.head;return this.head=this.head.next,null==this.head?this.tail=void 0:this.head.prev=void 0,--this.size,e?.data}peekFirst(){return this.head?.data}peekLast(){return this.tail?.data}clear(){this.head=void 0,this.tail=void 0,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 ${worker;info;usage;strategyData;messageChannel;tasksQueueBackPressureSize;onBackPressure;onEmptyQueue;tasksQueue;onBackPressureStarted;onEmptyQueueCount;taskFunctionsUsage;constructor(e,t){((e,t)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker");if(null==t)throw new TypeError("Cannot construct a worker node without a tasks queue back pressure size");if(!Number.isSafeInteger(t))throw new TypeError("Cannot construct a worker node with a tasks queue back pressure size that is not an integer");if(t<=0)throw new RangeError("Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer")})(e,t),this.worker=e,this.info=this.initWorkerInfo(e),this.usage=this.initWorkerUsage(),this.info.type===l.thread&&(this.messageChannel=new o.MessageChannel),this.tasksQueueBackPressureSize=t,this.tasksQueue=new V,this.onBackPressureStarted=!1,this.onEmptyQueueCount=0,this.taskFunctionsUsage=new Map}tasksQueueSize(){return this.tasksQueue.size}enqueueTask(e){const t=this.tasksQueue.push(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}unshiftTask(e){const t=this.tasksQueue.unshift(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}dequeueTask(){const e=this.tasksQueue.shift();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(m),e}popTask(){const e=this.tasksQueue.pop();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(m),e}clearTasksQueue(){this.tasksQueue.clear()}hasBackPressure(){return this.tasksQueue.size>=this.tasksQueueBackPressureSize}resetUsage(){this.usage=this.initWorkerUsage(),this.taskFunctionsUsage.clear()}closeChannel(){null!=this.messageChannel&&(this.messageChannel?.port1.unref(),this.messageChannel?.port2.unref(),this.messageChannel?.port1.close(),this.messageChannel?.port2.close(),delete this.messageChannel)}getTaskFunctionWorkerUsage(e){if(!Array.isArray(this.info.taskFunctionNames))throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list is not yet defined`);if(Array.isArray(this.info.taskFunctionNames)&&this.info.taskFunctionNames.length<3)throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list has less than 3 elements`);return e===g&&(e=this.info.taskFunctionNames[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}deleteTaskFunctionWorkerUsage(e){return this.taskFunctionsUsage.delete(e)}async startOnEmptyQueue(){this.onEmptyQueueCount>0&&(this.usage.tasks.executing>0||this.tasksQueue.size>0)?this.onEmptyQueueCount=0:(++this.onEmptyQueueCount,this.onEmptyQueue?.(this.info.id),await(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()})(this.onEmptyQueueCount)),await this.startOnEmptyQueue())}initWorkerInfo(e){return{id:T(e),type:y(e),dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueue.size,t=()=>this.tasksQueue.maxSize;return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},stolen:0,failed:0},runTime:{history:new j},waitTime:{history:new j},elu:{idle:{history:new j},active:{history:new j}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===g&&e===this.info.taskFunctionNames[1]||s.name!==g&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},stolen:0,failed:0},runTime:{history:new j},waitTime:{history:new j},elu:{idle:{history:new j},active:{history:new j}}}}}class G{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;taskFunctions;started;starting;startTimestamp;constructor(e,s,r){if(this.numberOfWorkers=e,this.filePath=s,this.opts=r,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");(e=>{if(null==e||"string"!=typeof e||"string"==typeof e&&0===e.trim().length)throw new Error("Please specify a file with a worker implementation");if(!t.existsSync(e))throw new Error(`Cannot find the worker file '${e}'`)})(this.filePath),this.checkNumberOfWorkers(this.numberOfWorkers),this.checkPoolOptions(this.opts),this.chooseWorkerNode=this.chooseWorkerNode.bind(this),this.executeTask=this.executeTask.bind(this),this.enqueueTask=this.enqueueTask.bind(this),!0===this.opts.enableEvents&&(this.emitter=new c),this.workerChoiceStrategyContext=new _(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.taskFunctions=new Map,this.started=!1,this.starting=!1,!0===this.opts.startWorkers&&this.start(),this.startTimestamp=n.performance.now()}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new TypeError("Cannot instantiate a pool with a non safe integer number of workers");if(e<0)throw new RangeError("Cannot instantiate a pool with a negative number of workers");if(this.type===k.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkPoolOptions(e){if(!S(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.startWorkers=e.startWorkers??!0,R(e.workerChoiceStrategy),this.opts.workerChoiceStrategy=e.workerChoiceStrategy??C.ROUND_ROBIN,this.checkValidWorkerChoiceStrategyOptions(e.workerChoiceStrategyOptions),this.opts.workerChoiceStrategyOptions={...p,...e.workerChoiceStrategyOptions},this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(z(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategyOptions(e){if(null!=e&&!S(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e?.retries&&!Number.isSafeInteger(e.retries))throw new TypeError("Invalid worker choice strategy options: retries must be an integer");if(null!=e?.retries&&e.retries<0)throw new RangeError(`Invalid worker choice strategy options: retries '${e.retries}' must be greater or equal than zero`);if(null!=e?.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e?.measurement&&!Object.values(O).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}get info(){return{version:"2.7.2",type:this.type,worker:this.worker,started:this.started,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:W(this.utilization)},workerNodes:this.workerNodes.length,idleWorkerNodes:this.workerNodes.reduce(((e,t)=>0===t.usage.tasks.executing?e+1:e),0),busyWorkerNodes:this.workerNodes.reduce(((e,t)=>t.usage.tasks.executing>0?e+1:e),0),executedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executed),0),executingTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executing),0),...!0===this.opts.enableTasksQueue&&{queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0)},...!0===this.opts.enableTasksQueue&&{maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.maxQueued??0)),0)},...!0===this.opts.enableTasksQueue&&{backPressure:this.hasBackPressure()},...!0===this.opts.enableTasksQueue&&{stolenTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.stolen),0)},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:W(b(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:W(I(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&{average:W(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:W(N(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:W(b(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:W(I(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&{average:W(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:W(N(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(n.performance.now()-this.startTimestamp)*this.maxSize;return(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)+this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0))/e}get minSize(){return this.numberOfWorkers}get maxSize(){return this.max??this.numberOfWorkers}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Worker message received without worker id");if(null!=e.workerId&&-1===this.getWorkerNodeKeyByWorkerId(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKeyByWorker(e){return this.workerNodes.findIndex((t=>t.worker===e))}getWorkerNodeKeyByWorkerId(e){return this.workerNodes.findIndex((t=>t.info.id===e))}setWorkerChoiceStrategy(e,t){R(e),this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(this.opts.workerChoiceStrategy),null!=t&&this.setWorkerChoiceStrategyOptions(t);for(const[e,t]of this.workerNodes.entries())t.resetUsage(),this.sendStatisticsMessageToWorker(e)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions={...p,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||(this.unsetTaskStealing(),this.unsetTasksStealingOnBackPressure(),this.flushTasksQueues()),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(z(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e),this.setTasksQueueSize(this.opts.tasksQueueOptions.size),!0===this.opts.tasksQueueOptions.taskStealing?this.setTaskStealing():this.unsetTaskStealing(),!0===this.opts.tasksQueueOptions.tasksStealingOnBackPressure?this.setTasksStealingOnBackPressure():this.unsetTasksStealingOnBackPressure()):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{size:Math.pow(this.maxSize,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,...e}}setTasksQueueSize(e){for(const t of this.workerNodes)t.tasksQueueBackPressureSize=e}setTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)}unsetTaskStealing(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onEmptyQueue}setTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)}unsetTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onBackPressure}get full(){return this.workerNodes.length>=this.maxSize}internalBusy(){return!0===this.opts.enableTasksQueue?-1===this.workerNodes.findIndex((e=>e.info.ready&&e.usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency)):-1===this.workerNodes.findIndex((e=>e.info.ready&&0===e.usage.tasks.executing))}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(((i,o)=>{if(!this.started)return void o(new Error("Cannot execute a task on not started pool"));if(null!=t&&"string"!=typeof t)return void o(new TypeError("name argument must be a string"));if(null!=t&&"string"==typeof t&&0===t.trim().length)return void o(new TypeError("name argument must not be an empty string"));if(null!=s&&!Array.isArray(s))return void o(new TypeError("transferList argument must be an array"));const a=n.performance.now(),u=this.chooseWorkerNode(),h={name:t??g,data:e??{},transferList:s,timestamp:a,taskId:r.randomUUID()};this.promiseResponseMap.set(h.taskId,{resolve:i,reject:o,workerNodeKey:u}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.shallExecuteTask(u)?this.executeTask(u,h):this.enqueueTask(u,h)}))}start(){for(this.starting=!0;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode();this.starting=!1,this.started=!0}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(d.destroy,this.info),this.started=!1}async sendKillMessageToWorker(e){await new Promise(((t,s)=>{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})}))}setupHook(){}beforeTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}}afterTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name);this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return null!=t&&Array.isArray(t.taskFunctionNames)&&t.taskFunctionNames.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;null!=s.executing&&s.executing>0&&--s.executing,null==t.workerError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){null==t.workerError&&P(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0)}updateWaitTimeWorkerUsage(e,t){const s=n.performance.now(),r=s-(t.timestamp??s);P(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r)}updateEluWorkerUsage(e,t){if(null!=t.workerError)return;const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;P(e.elu.active,s,t.taskPerformance?.elu?.active??0),P(e.elu.idle,s,t.taskPerformance?.elu?.idle??0),s.aggregate&&null!=t.taskPerformance?.elu&&(null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization)}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorkerNode();if(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===k.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorker();e.on("online",this.opts.onlineHandler??m),e.on("message",this.opts.messageHandler??m),e.on("error",this.opts.errorHandler??m),e.on("error",(t=>{const s=this.getWorkerNodeKeyByWorker(e),r=this.getWorkerInfo(s);r.ready=!1,this.workerNodes[s].closeChannel(),this.emitter?.emit(d.error,t),this.started&&!this.starting&&!0===this.opts.restartWorkerOnError&&(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),this.started&&!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(s)})),e.on("exit",this.opts.exitHandler??m),e.once("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;(x(M.HARD,e.kill)||x(M.SOFT,e.kill)&&(!1===this.opts.enableTasksQueue&&0===s.tasks.executing||!0===this.opts.enableTasksQueue&&0===s.tasks.executing&&0===this.tasksQueueSize(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.workerListener()),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e),!0===this.opts.enableTasksQueue&&(!0===this.opts.tasksQueueOptions?.taskStealing&&(this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)),!0===this.opts.tasksQueueOptions?.tasksStealingOnBackPressure&&(this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)))}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate}})}redistributeQueuedTasks(e){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),s=this.dequeueTask(e);this.shallExecuteTask(t)?this.executeTask(t,s):this.enqueueTask(t,s)}}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}}taskStealingOnEmptyQueue(e){const t=this.getWorkerNodeKeyByWorkerId(e),s=this.workerNodes.slice().sort(((e,t)=>t.usage.tasks.queued-e.usage.tasks.queued)).find((t=>t.info.ready&&t.info.id!==e&&t.usage.tasks.queued>0));if(null!=s){const e=s.popTask();this.shallExecuteTask(t)?this.executeTask(t,e):this.enqueueTask(t,e),this.updateTaskStolenStatisticsWorkerUsage(t,e.name)}}tasksStealingOnBackPressure(e){if(this.opts.tasksQueueOptions?.size<=1)return;const t=this.workerNodes[this.getWorkerNodeKeyByWorkerId(e)],s=this.workerNodes.slice().sort(((e,t)=>e.usage.tasks.queued-t.usage.tasks.queued));for(const[r,i]of s.entries())if(t.usage.tasks.queued>0&&i.info.ready&&i.info.id!==e&&i.usage.tasks.queued<this.opts.tasksQueueOptions?.size-1){const e=t.popTask();this.shallExecuteTask(r)?this.executeTask(r,e):this.enqueueTask(r,e),this.updateTaskStolenStatisticsWorkerUsage(r,e.name)}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctionNames?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctionNames&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctionNames=e.taskFunctionNames)}}handleWorkerReadyResponse(e){if(!1===e.ready)throw new Error(`Worker ${e.workerId} failed to initialize`);const t=this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId));t.ready=e.ready,t.taskFunctionNames=e.taskFunctionNames,this.ready&&this.emitter?.emit(d.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,workerError:s,data:r}=e,i=this.promiseResponseMap.get(t);if(null!=i){null!=s?(this.emitter?.emit(d.taskError,s),i.reject(s.message)):i.resolve(r);const o=i.workerNodeKey;this.afterTaskExecutionHook(o,e),this.workerChoiceStrategyContext.update(o),this.promiseResponseMap.delete(t),!0===this.opts.enableTasksQueue&&this.tasksQueueSize(o)>0&&this.workerNodes[o].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&this.executeTask(o,this.dequeueTask(o))}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(d.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(d.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===k.dynamic&&this.full&&this.emitter?.emit(d.full,this.info)}getWorkerInfo(e){return this.workerNodes[e].info}addWorkerNode(e){const t=new $(e,this.opts.tasksQueueOptions?.size??Math.pow(this.maxSize,2));this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker added not found in worker nodes");return s}removeWorkerNode(e){const t=this.getWorkerNodeKeyByWorker(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}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){for(;this.tasksQueueSize(e)>0;)this.executeTask(e,this.dequeueTask(e));this.workerNodes[e].clearTasksQueue()}flushTasksQueues(){for(const[e]of this.workerNodes.entries())this.flushTasksQueue(e)}}class Y extends G{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){i.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return i.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.once("exit",(()=>{e()}))}));t.once("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send({...t,workerId:this.workerNodes[e].info.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)}createWorker(){return i.fork(this.opts.env)}get type(){return k.fixed}get worker(){return l.cluster}get busy(){return this.internalBusy()}}class J extends G{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return o.isMainThread}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.once("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage({...t,workerId:this.workerNodes[e].info.id},s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e],s=t.messageChannel.port2;t.worker.postMessage({ready:!1,workerId:t.info.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)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV,...this.opts.workerOptions})}get type(){return k.fixed}get worker(){return l.thread}get busy(){return this.internalBusy()}}const X=(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")},Z=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")},ee=6e4,te={killBehavior:M.SOFT,maxInactiveTime:ee,killHandler:m};class se extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=te){if(super(e),this.isMain=t,this.mainWorker=s,this.opts=i,null==this.isMain)throw new Error("isMain parameter is mandatory");this.checkTaskFunctions(r),this.checkWorkerOptions(this.opts),this.isMain||this.getMainWorker().on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){(e=>{if(null!=e&&!S(e))throw new TypeError("opts worker options parameter is not a plain object");if(null!=e?.killBehavior&&!Object.values(M).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");if(null!=e?.async)throw new Error("async option is deprecated")})(e),this.opts={...te,...e}}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e){const t=e.bind(this);this.taskFunctions.set(g,t),this.taskFunctions.set("string"==typeof e.name&&e.name.trim().length>0?e.name:"fn1",t)}else{if(!S(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){X(s,r);const e=r.bind(this);t&&(this.taskFunctions.set(g,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){try{Z(e)}catch(e){return{status:!1,error:e}}return{status:this.taskFunctions.has(e)}}addTaskFunction(e,t){try{if(Z(e),e===g)throw new Error("Cannot add a task function with the default reserved name");if("function"!=typeof t)throw new TypeError("fn parameter is not a function");const s=t.bind(this);return this.taskFunctions.get(e)===this.taskFunctions.get(g)&&this.taskFunctions.set(g,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(Z(e),e===g)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(g))throw new Error("Cannot remove the task function used as the default task function");const t=this.taskFunctions.delete(e);return this.sendTaskFunctionNamesToMainWorker(),{status:t}}catch(e){return{status:!1,error:e}}}listTaskFunctionNames(){const e=[...this.taskFunctions.keys()];let t=g;for(const[e,s]of this.taskFunctions)if(e!==g&&s===this.taskFunctions.get(g)){t=e;break}return[e[e.indexOf(g)],t,...e.filter((e=>e!==g&&e!==t))]}setDefaultTaskFunction(e){try{if(Z(e),e===g)throw new Error("Cannot set the default task function reserved name as the default task function");if(!this.taskFunctions.has(e))throw new Error("Cannot set the default task function to a non-existing task function");return this.taskFunctions.set(g,this.taskFunctions.get(e)),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskFunctionOperation?this.handleTaskFunctionOperationMessage(e):null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleTaskFunctionOperationMessage(e){const{taskFunctionOperation:t,taskFunctionName:s,taskFunction:r}=e;let i;switch(t){case"add":i=this.addTaskFunction(s,new Function(`return ${r}`)());break;case"remove":i=this.removeTaskFunction(s);break;case"default":i=this.setDefaultTaskFunction(s);break;default:i={status:!1,error:new Error("Unknown task operation")}}this.sendToMainWorker({taskFunctionOperation:t,taskFunctionOperationStatus:i.status,taskFunctionName:s,...!i.status&&null!=i?.error&&{workerError:{name:s,message:this.handleError(i.error)}}})}handleKillMessage(e){if(this.stopCheckActive(),E(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>(this.sendToMainWorker({kill:"success"}),null))).catch((()=>{this.sendToMainWorker({kill:"failure"})})).finally((()=>{this.emitDestroy()})).catch(m);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success"})}catch{this.sendToMainWorker({kill:"failure"})}finally{this.emitDestroy()}}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Message worker id is not set");if(null!=e.workerId&&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??ee)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){n.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??ee)&&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=this.taskFunctions.get(t??g);null!=i?E(i)?this.runInAsyncScope(this.runAsync.bind(this),this,i,e):this.runInAsyncScope(this.runSync.bind(this),this,i,e):this.sendToMainWorker({workerError:{name:t,message:`Task function '${t}' not found`,data:r},taskId:s})}runSync(e,t){const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,taskId:r})}catch(e){this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})}finally{this.updateLastTaskTimestamp()}}runAsync(e,t){const{name:s,taskId:r,data:i}=t;let o=this.beginTaskPerformance(s);e(i).then((e=>{o=this.endTaskPerformance(o),this.sendToMainWorker({data:e,taskPerformance:o,taskId:r})})).catch((e=>{this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(m)}beginTaskPerformance(e){return this.checkStatistics(),{name:e??g,timestamp:n.performance.now(),...this.statistics.elu&&{elu:n.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:n.performance.now()-e.timestamp},...this.statistics.elu&&{elu:n.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=n.performance.now())}}exports.ClusterWorker=class extends se{constructor(e,t={}){super("worker-cluster-pool:poolifier",i.isPrimary,i.worker,e,t)}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 Y{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,F(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends J{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,F(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=Y,exports.FixedThreadPool=J,exports.KillBehaviors=M,exports.Measurements=O,exports.PoolEvents=d,exports.PoolTypes=k,exports.ThreadWorker=class extends se{port;constructor(e,t={}){super("worker-thread-pool:poolifier",o.isMainThread,o.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 o.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=h.availableParallelism()}catch{const t=h.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
"use strict";var e=require("node:fs"),t=require("node:os"),s=require("node:crypto"),r=require("node:cluster"),i=require("node:worker_threads"),o=require("node:perf_hooks"),n=require("node:events"),a=require("node:async_hooks");function u(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 h=u(t);const k=Object.freeze({fixed:"fixed",dynamic:"dynamic"}),c=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),d=Object.freeze({thread:"thread",cluster:"cluster"}),l="default",g=Object.freeze((()=>{})),m={retries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},p={aggregate:!1,average:!1,median:!1},w=e=>e instanceof i.Worker?d.thread:e instanceof r.Worker?d.cluster:void 0,y=e=>e instanceof i.Worker?e.threadId:e instanceof r.Worker?e.id:void 0,T=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,f=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,E=()=>s.webcrypto.getRandomValues(new Uint32Array(1))[0]/4294967296,v=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),b=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),I=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"}),C=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),O=(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")},F=e=>{if(null!=e&&!Object.values(I).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},R=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`)},z=(e,t,s)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=v(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=T(e.history):null!=e.average&&delete e.average,t.median?e.median=f(e.history):null!=e.median&&delete e.median))},P=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class M{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:p,waitTime:p,elu:p};constructor(e,t=m){this.pool=e,this.opts=t,this.opts={...m,...t},this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.runTime,e.runTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.waitTime,e.waitTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.elu,e.elu?.median)}toggleMedianMeasurementStatisticsRequirements(e,t){e.average&&t&&(e.average=!1,e.median=t),e.median&&!t&&(e.average=!0,e.median=t)}resetWorkerNodeKeyProperties(){this.nextWorkerNodeKey=0,this.previousWorkerNodeKey=0}setOptions(e){this.opts={...m,...e},this.setTaskStatisticsRequirements(this.opts)}isWorkerNodeReady(e){return this.pool.workerNodes[e].info.ready}hasWorkerNodeBackPressure(e){return this.pool.hasWorkerNodeBackPressure(e)}isWorkerNodeEligible(e){return this.isWorkerNodeReady(e)&&!this.hasWorkerNodeBackPressure(e)}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}checkNextWorkerNodeEligibility(){this.isWorkerNodeEligible(this.nextWorkerNodeKey)||(this.nextWorkerNodeKey=void 0)}computeDefaultWorkerWeight(){let e=0;for(const s of t.cpus()){const t=s.speed.toString().length-1;e+=1/(s.speed/Math.pow(10,t))*Math.pow(10,t)}return Math.round(e/t.cpus().length)}}class Q extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:{aggregate:!0,average:!0,median:!1}};constructor(e,t=m){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)}),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===C.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 K extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};roundId=0;defaultWorkerWeight;roundWeights;workerNodeId=0;workerNodeVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,this.workerNodeId=0,this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){for(let e=this.roundId;e<this.roundWeights.length;e++){this.roundId=e;for(let t=this.workerNodeId;t<this.pool.workerNodes.length;t++){this.workerNodeId=t,this.workerNodeId!==this.nextWorkerNodeKey&&0!==this.workerNodeVirtualTaskRunTime&&(this.workerNodeVirtualTaskRunTime=0);const s=this.opts.weights?.[t]??this.defaultWorkerWeight;if(s>=this.roundWeights[e]&&this.workerNodeVirtualTaskRunTime<s)return this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(t),this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=t,this.nextWorkerNodeKey}}this.interleavedWeightedRoundRobinNextWorkerNodeId()}interleavedWeightedRoundRobinNextWorkerNodeId(){this.roundId===this.roundWeights.length-1&&this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=0,this.workerNodeId=0):this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=this.roundId+1,this.workerNodeId=0):this.workerNodeId=this.workerNodeId+1}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.workerNodeId===e&&this.workerNodeId>this.pool.workerNodes.length-1&&(this.workerNodeId=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}setOptions(e){super.setOptions(e),this.roundWeights=this.getRoundWeights()}getRoundWeights(){return null==this.opts.weights?[this.defaultWorkerWeight]:[...new Set(Object.values(this.opts.weights).slice().sort(((e,t)=>e-t)))]}}class q extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:p};constructor(e,t=m){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)=>(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 B extends M{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>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 A extends M{taskStatisticsRequirements={runTime:p,waitTime:p,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=m){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)=>(t.usage.elu.active.aggregate??0)<(r[e].usage.elu.active.aggregate??0)?s:e),0)}}class U extends M{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.setPreviousWorkerNodeKey(e),this.roundRobinNextWorkerNodeKey(),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 D extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};defaultWorkerWeight;workerNodeVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.weightedRoundRobinNextWorkerNodeKey()}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&(this.workerNodeVirtualTaskRunTime=0,this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight;return this.workerNodeVirtualTaskRunTime<e?this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerNodeVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class L{workerChoiceStrategy;opts;workerChoiceStrategies;retriesCount=0;constructor(e,t=I.ROUND_ROBIN,s=m){this.workerChoiceStrategy=t,this.opts=s,this.opts={...m,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[I.ROUND_ROBIN,new(U.bind(this))(e,s)],[I.LEAST_USED,new(B.bind(this))(e,s)],[I.LEAST_BUSY,new(q.bind(this))(e,s)],[I.LEAST_ELU,new(A.bind(this))(e,s)],[I.FAIR_SHARE,new(Q.bind(this))(e,s)],[I.WEIGHTED_ROUND_ROBIN,new(D.bind(this))(e,s)],[I.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(K.bind(this))(e,s)]])}getStrategyPolicy(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).strategyPolicy}getTaskStatisticsRequirements(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).taskStatisticsRequirements}setWorkerChoiceStrategy(e){this.workerChoiceStrategy!==e&&(this.workerChoiceStrategy=e),this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()}update(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).update(e)}execute(){const e=this.workerChoiceStrategies.get(this.workerChoiceStrategy).choose();if(null==e&&this.retriesCount<this.opts.retries)return this.retriesCount++,this.execute();if(null==e)throw new Error(`Worker node key chosen is null or undefined after ${this.retriesCount} retries`);return this.retriesCount=0,e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...m,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class _ 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 _(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 j{data;next;prev;constructor(e){this.data=e}}class H{head;tail;size;maxSize;constructor(){this.clear()}push(e){const t=new j(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 j(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?this.head=void 0:this.tail.next=void 0,--this.size,e?.data}shift(){if(null==this.head)return;const e=this.head;return this.head=this.head.next,null==this.head?this.tail=void 0:this.head.prev=void 0,--this.size,e?.data}peekFirst(){return this.head?.data}peekLast(){return this.tail?.data}clear(){this.head=void 0,this.tail=void 0,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 V{worker;info;usage;strategyData;messageChannel;tasksQueueBackPressureSize;onBackPressure;onEmptyQueue;tasksQueue;onBackPressureStarted;onEmptyQueueCount;taskFunctionsUsage;constructor(e,t){((e,t)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker");if(null==t)throw new TypeError("Cannot construct a worker node without a tasks queue back pressure size");if(!Number.isSafeInteger(t))throw new TypeError("Cannot construct a worker node with a tasks queue back pressure size that is not an integer");if(t<=0)throw new RangeError("Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer")})(e,t),this.worker=e,this.info=this.initWorkerInfo(e),this.usage=this.initWorkerUsage(),this.info.type===d.thread&&(this.messageChannel=new i.MessageChannel),this.tasksQueueBackPressureSize=t,this.tasksQueue=new H,this.onBackPressureStarted=!1,this.onEmptyQueueCount=0,this.taskFunctionsUsage=new Map}tasksQueueSize(){return this.tasksQueue.size}enqueueTask(e){const t=this.tasksQueue.push(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}unshiftTask(e){const t=this.tasksQueue.unshift(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}dequeueTask(){const e=this.tasksQueue.shift();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(g),e}popTask(){const e=this.tasksQueue.pop();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(g),e}clearTasksQueue(){this.tasksQueue.clear()}hasBackPressure(){return this.tasksQueue.size>=this.tasksQueueBackPressureSize}resetUsage(){this.usage=this.initWorkerUsage(),this.taskFunctionsUsage.clear()}closeChannel(){null!=this.messageChannel&&(this.messageChannel?.port1.unref(),this.messageChannel?.port2.unref(),this.messageChannel?.port1.close(),this.messageChannel?.port2.close(),delete this.messageChannel)}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===l&&(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)}async startOnEmptyQueue(){this.onEmptyQueueCount>0&&(this.usage.tasks.executing>0||this.tasksQueue.size>0)?this.onEmptyQueueCount=0:(++this.onEmptyQueueCount,this.onEmptyQueue?.(this.info.id),await(async e=>{await new Promise((t=>{setTimeout(t,e)}))})(((e=0,t=100)=>{const s=Math.pow(2,e)*t;return s+.2*s*E()})(this.onEmptyQueueCount)),await this.startOnEmptyQueue())}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()},stolen:0,failed:0},runTime:{history:new _},waitTime:{history:new _},elu:{idle:{history:new _},active:{history:new _}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===l&&e===this.info.taskFunctionNames[1]||s.name!==l&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},stolen:0,failed:0},runTime:{history:new _},waitTime:{history:new _},elu:{idle:{history:new _},active:{history:new _}}}}}class ${numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;taskFunctions;started;starting;startTimestamp;constructor(t,s,r){if(this.numberOfWorkers=t,this.filePath=s,this.opts=r,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");(t=>{if(null==t||"string"!=typeof t||"string"==typeof t&&0===t.trim().length)throw new Error("Please specify a file with a worker implementation");if(!e.existsSync(t))throw new Error(`Cannot find the worker file '${t}'`)})(this.filePath),this.checkNumberOfWorkers(this.numberOfWorkers),this.checkPoolOptions(this.opts),this.chooseWorkerNode=this.chooseWorkerNode.bind(this),this.executeTask=this.executeTask.bind(this),this.enqueueTask=this.enqueueTask.bind(this),!0===this.opts.enableEvents&&this.initializeEventEmitter(),this.workerChoiceStrategyContext=new L(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.taskFunctions=new Map,this.started=!1,this.starting=!1,!0===this.opts.startWorkers&&this.start(),this.startTimestamp=o.performance.now()}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new TypeError("Cannot instantiate a pool with a non safe integer number of workers");if(e<0)throw new RangeError("Cannot instantiate a pool with a negative number of workers");if(this.type===k.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,F(e.workerChoiceStrategy),this.opts.workerChoiceStrategy=e.workerChoiceStrategy??I.ROUND_ROBIN,this.checkValidWorkerChoiceStrategyOptions(e.workerChoiceStrategyOptions),this.opts.workerChoiceStrategyOptions={...m,...e.workerChoiceStrategyOptions},this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(R(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?.retries&&!Number.isSafeInteger(e.retries))throw new TypeError("Invalid worker choice strategy options: retries must be an integer");if(null!=e?.retries&&e.retries<0)throw new RangeError(`Invalid worker choice strategy options: retries '${e.retries}' must be greater or equal than zero`);if(null!=e?.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e?.measurement&&!Object.values(C).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}initializeEventEmitter(){this.emitter=new n.EventEmitterAsyncResource({name:`poolifier:${this.type}-${this.worker}-pool`})}get info(){return{version:"2.7.3",type:this.type,worker:this.worker,started:this.started,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization: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)=>t.usage.tasks.executing>0?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(v(...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(T(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:N(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:N(v(...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(T(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:N(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(o.performance.now()-this.startTimestamp)*this.maxSize;return(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)+this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0))/e}get minSize(){return this.numberOfWorkers}get maxSize(){return this.max??this.numberOfWorkers}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Worker message received without worker id");if(null!=e.workerId&&-1===this.getWorkerNodeKeyByWorkerId(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKeyByWorker(e){return this.workerNodes.findIndex((t=>t.worker===e))}getWorkerNodeKeyByWorkerId(e){return this.workerNodes.findIndex((t=>t.info.id===e))}setWorkerChoiceStrategy(e,t){F(e),this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(this.opts.workerChoiceStrategy),null!=t&&this.setWorkerChoiceStrategyOptions(t);for(const[e,t]of this.workerNodes.entries())t.resetUsage(),this.sendStatisticsMessageToWorker(e)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions={...m,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||(this.unsetTaskStealing(),this.unsetTasksStealingOnBackPressure(),this.flushTasksQueues()),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(R(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e),this.setTasksQueueSize(this.opts.tasksQueueOptions.size),!0===this.opts.tasksQueueOptions.taskStealing?this.setTaskStealing():this.unsetTaskStealing(),!0===this.opts.tasksQueueOptions.tasksStealingOnBackPressure?this.setTasksStealingOnBackPressure():this.unsetTasksStealingOnBackPressure()):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{size:Math.pow(this.maxSize,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,...e}}setTasksQueueSize(e){for(const t of this.workerNodes)t.tasksQueueBackPressureSize=e}setTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)}unsetTaskStealing(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onEmptyQueue}setTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)}unsetTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onBackPressure}get full(){return this.workerNodes.length>=this.maxSize}internalBusy(){return!0===this.opts.enableTasksQueue?-1===this.workerNodes.findIndex((e=>e.info.ready&&e.usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency)):-1===this.workerNodes.findIndex((e=>e.info.ready&&0===e.usage.tasks.executing))}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,r){return await new Promise(((i,n)=>{if(!this.started)return void n(new Error("Cannot execute a task on not started pool"));if(null!=t&&"string"!=typeof t)return void n(new TypeError("name argument must be a string"));if(null!=t&&"string"==typeof t&&0===t.trim().length)return void n(new TypeError("name argument must not be an empty string"));if(null!=r&&!Array.isArray(r))return void n(new TypeError("transferList argument must be an array"));const a=o.performance.now(),u=this.chooseWorkerNode(),h={name:t??l,data:e??{},transferList:r,timestamp:a,taskId:s.randomUUID()};this.promiseResponseMap.set(h.taskId,{resolve:i,reject:n,workerNodeKey:u}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.shallExecuteTask(u)?this.executeTask(u,h):this.enqueueTask(u,h)}))}start(){for(this.starting=!0;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode();this.starting=!1,this.started=!0}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(c.destroy,this.info),this.emitter instanceof n.EventEmitterAsyncResource&&this.emitter?.emitDestroy(),this.started=!1}async sendKillMessageToWorker(e){await new Promise(((t,s)=>{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})}))}setupHook(){}beforeTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}}afterTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name);this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return null!=t&&Array.isArray(t.taskFunctionNames)&&t.taskFunctionNames.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;null!=s.executing&&s.executing>0&&--s.executing,null==t.workerError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){null==t.workerError&&z(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0)}updateWaitTimeWorkerUsage(e,t){const s=o.performance.now(),r=s-(t.timestamp??s);z(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r)}updateEluWorkerUsage(e,t){if(null!=t.workerError)return;const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;z(e.elu.active,s,t.taskPerformance?.elu?.active??0),z(e.elu.idle,s,t.taskPerformance?.elu?.idle??0),s.aggregate&&null!=t.taskPerformance?.elu&&(null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization)}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorkerNode();if(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===k.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorker();e.on("online",this.opts.onlineHandler??g),e.on("message",this.opts.messageHandler??g),e.on("error",this.opts.errorHandler??g),e.on("error",(t=>{const s=this.getWorkerNodeKeyByWorker(e),r=this.getWorkerInfo(s);r.ready=!1,this.workerNodes[s].closeChannel(),this.emitter?.emit(c.error,t),this.started&&!this.starting&&!0===this.opts.restartWorkerOnError&&(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),this.started&&!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(s)})),e.on("exit",this.opts.exitHandler??g),e.once("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(P.HARD,e.kill)||S(P.SOFT,e.kill)&&(!1===this.opts.enableTasksQueue&&0===s.tasks.executing||!0===this.opts.enableTasksQueue&&0===s.tasks.executing&&0===this.tasksQueueSize(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.workerListener()),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e),!0===this.opts.enableTasksQueue&&(!0===this.opts.tasksQueueOptions?.taskStealing&&(this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)),!0===this.opts.tasksQueueOptions?.tasksStealingOnBackPressure&&(this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)))}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate}})}redistributeQueuedTasks(e){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),s=this.dequeueTask(e);this.shallExecuteTask(t)?this.executeTask(t,s):this.enqueueTask(t,s)}}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}}taskStealingOnEmptyQueue(e){const t=this.getWorkerNodeKeyByWorkerId(e),s=this.workerNodes.slice().sort(((e,t)=>t.usage.tasks.queued-e.usage.tasks.queued)).find((t=>t.info.ready&&t.info.id!==e&&t.usage.tasks.queued>0));if(null!=s){const e=s.popTask();this.shallExecuteTask(t)?this.executeTask(t,e):this.enqueueTask(t,e),this.updateTaskStolenStatisticsWorkerUsage(t,e.name)}}tasksStealingOnBackPressure(e){if(this.opts.tasksQueueOptions?.size<=1)return;const t=this.workerNodes[this.getWorkerNodeKeyByWorkerId(e)],s=this.workerNodes.slice().sort(((e,t)=>e.usage.tasks.queued-t.usage.tasks.queued));for(const[r,i]of s.entries())if(t.usage.tasks.queued>0&&i.info.ready&&i.info.id!==e&&i.usage.tasks.queued<this.opts.tasksQueueOptions?.size-1){const e=t.popTask();this.shallExecuteTask(r)?this.executeTask(r,e):this.enqueueTask(r,e),this.updateTaskStolenStatisticsWorkerUsage(r,e.name)}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctionNames?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctionNames&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctionNames=e.taskFunctionNames)}}handleWorkerReadyResponse(e){if(!1===e.ready)throw new Error(`Worker ${e.workerId} failed to initialize`);const t=this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId));t.ready=e.ready,t.taskFunctionNames=e.taskFunctionNames,this.ready&&this.emitter?.emit(c.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,workerError:s,data:r}=e,i=this.promiseResponseMap.get(t);if(null!=i){null!=s?(this.emitter?.emit(c.taskError,s),i.reject(s.message)):i.resolve(r);const o=i.workerNodeKey;this.afterTaskExecutionHook(o,e),this.workerChoiceStrategyContext.update(o),this.promiseResponseMap.delete(t),!0===this.opts.enableTasksQueue&&this.tasksQueueSize(o)>0&&this.workerNodes[o].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&this.executeTask(o,this.dequeueTask(o))}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(c.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(c.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===k.dynamic&&this.full&&this.emitter?.emit(c.full,this.info)}getWorkerInfo(e){return this.workerNodes[e].info}addWorkerNode(e){const t=new V(e,this.opts.tasksQueueOptions?.size??Math.pow(this.maxSize,2));this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker added not found in worker nodes");return s}removeWorkerNode(e){const t=this.getWorkerNodeKeyByWorker(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}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){for(;this.tasksQueueSize(e)>0;)this.executeTask(e,this.dequeueTask(e));this.workerNodes[e].clearTasksQueue()}flushTasksQueues(){for(const[e]of this.workerNodes.entries())this.flushTasksQueue(e)}}class G extends ${opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){r.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return r.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.once("exit",(()=>{e()}))}));t.once("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send({...t,workerId:this.workerNodes[e].info.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)}createWorker(){return r.fork(this.opts.env)}get type(){return k.fixed}get worker(){return d.cluster}get busy(){return this.internalBusy()}}class Y extends ${opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return i.isMainThread}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.once("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage({...t,workerId:this.workerNodes[e].info.id},s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e],s=t.messageChannel.port2;t.worker.postMessage({ready:!1,workerId:t.info.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)}createWorker(){return new i.Worker(this.filePath,{env:i.SHARE_ENV,...this.opts.workerOptions})}get type(){return k.fixed}get worker(){return d.thread}get busy(){return this.internalBusy()}}const J=(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")},X=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")},Z=6e4,ee={killBehavior:P.SOFT,maxInactiveTime:Z,killHandler:g};class te extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=ee){if(super(e),this.isMain=t,this.mainWorker=s,this.opts=i,null==this.isMain)throw new Error("isMain parameter is mandatory");this.checkTaskFunctions(r),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(P).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");if(null!=e?.async)throw new Error("async option is deprecated")})(e),this.opts={...ee,...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(l,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)){J(s,r);const e=r.bind(this);t&&(this.taskFunctions.set(l,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){try{X(e)}catch(e){return{status:!1,error:e}}return{status:this.taskFunctions.has(e)}}addTaskFunction(e,t){try{if(X(e),e===l)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(l)&&this.taskFunctions.set(l,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(X(e),e===l)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(l))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=l;for(const[e,s]of this.taskFunctions)if(e!==l&&s===this.taskFunctions.get(l)){t=e;break}return[e[e.indexOf(l)],t,...e.filter((e=>e!==l&&e!==t))]}setDefaultTaskFunction(e){try{if(X(e),e===l)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(l,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"}),null))).catch((()=>{this.sendToMainWorker({kill:"failure"})})).finally((()=>{this.emitDestroy()})).catch(g);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success"})}catch{this.sendToMainWorker({kill:"failure"})}finally{this.emitDestroy()}}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Message worker id is not set");if(null!=e.workerId&&e.workerId!==this.id)throw new Error(`Message worker id ${e.workerId} does not match the worker id ${this.id}`)}startCheckActive(){this.lastTaskTimestamp=o.performance.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??Z)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){o.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??Z)&&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=this.taskFunctions.get(t??l);null!=i?x(i)?this.runInAsyncScope(this.runAsync.bind(this),this,i,e):this.runInAsyncScope(this.runSync.bind(this),this,i,e):this.sendToMainWorker({workerError:{name:t,message:`Task function '${t}' not found`,data:r},taskId:s})}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??l,timestamp:o.performance.now(),...this.statistics.elu&&{elu:o.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:o.performance.now()-e.timestamp},...this.statistics.elu&&{elu:o.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=o.performance.now())}}exports.ClusterWorker=class extends te{constructor(e,t={}){super("poolifier:cluster-worker",r.isPrimary,r.worker,e,t)}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 G{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,O(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends Y{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,O(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=G,exports.FixedThreadPool=Y,exports.KillBehaviors=P,exports.Measurements=C,exports.PoolEvents=c,exports.PoolTypes=k,exports.ThreadWorker=class extends te{port;constructor(e,t={}){super("poolifier:thread-worker",i.isMainThread,i.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 i.threadId}sendToMainWorker(e){this.port.postMessage({...e,workerId:this.id})}handleError(e){return e}},exports.WorkerChoiceStrategies=I,exports.WorkerTypes=d,exports.availableParallelism=()=>{let e=1;try{e=h.availableParallelism()}catch{const t=h.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
//# sourceMappingURL=index.js.map

@@ -1,2 +0,2 @@

"use strict";var e=require("node:events"),t=require("node:fs"),s=require("node:os"),r=require("node:crypto"),i=require("node:cluster"),o=require("node:worker_threads"),n=require("node:perf_hooks"),a=require("node:async_hooks");function u(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 h=u(s);const k=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class c extends e.EventEmitter{}const d=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),l=Object.freeze({thread:"thread",cluster:"cluster"}),g="default",m=Object.freeze((()=>{})),p={retries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},w={aggregate:!1,average:!1,median:!1},y=e=>e instanceof o.Worker?l.thread:e instanceof i.Worker?l.cluster:void 0,T=e=>e instanceof o.Worker?e.threadId:e instanceof i.Worker?e.id:void 0,f=e=>Array.isArray(e)&&0===e.length?0:Array.isArray(e)&&1===e.length?e[0]:e.reduce(((e,t)=>e+t),0)/e.length,N=e=>{if(Array.isArray(e)&&0===e.length)return 0;if(Array.isArray(e)&&1===e.length)return e[0];const t=e.slice().sort(((e,t)=>e-t));return(t[t.length-1>>1]+t[t.length>>1])/2},W=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},S=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),x=(e,t)=>t===e,E=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,v=()=>r.webcrypto.getRandomValues(new Uint32Array(1))[0]/4294967296,b=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),I=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),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"}),O=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),F=(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")},R=e=>{if(null!=e&&!Object.values(C).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},z=e=>{if(null!=e&&!S(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker node tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new RangeError(`Invalid worker node tasks concurrency: ${e.concurrency} is a negative integer or zero`);if(null!=e?.size&&!Number.isSafeInteger(e.size))throw new TypeError("Invalid worker node tasks queue size: must be an integer");if(null!=e?.size&&e.size<=0)throw new RangeError(`Invalid worker node tasks queue size: ${e.size} is a negative integer or zero`)},P=(e,t,s)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=b(s,e.minimum??1/0),e.maximum=I(s,e.maximum??-1/0),(t.average||t.median)&&null!=s&&(e.history.push(s),t.average?e.average=f(e.history):null!=e.average&&delete e.average,t.median?e.median=N(e.history):null!=e.median&&delete e.median))},M=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class Q{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:w,waitTime:w,elu:w};constructor(e,t=p){this.pool=e,this.opts=t,this.opts={...p,...t},this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.runTime,e.runTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.waitTime,e.waitTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.elu,e.elu?.median)}toggleMedianMeasurementStatisticsRequirements(e,t){e.average&&t&&(e.average=!1,e.median=t),e.median&&!t&&(e.average=!0,e.median=t)}resetWorkerNodeKeyProperties(){this.nextWorkerNodeKey=0,this.previousWorkerNodeKey=0}setOptions(e){this.opts={...p,...e},this.setTaskStatisticsRequirements(this.opts)}isWorkerNodeReady(e){return this.pool.workerNodes[e].info.ready}hasWorkerNodeBackPressure(e){return this.pool.hasWorkerNodeBackPressure(e)}isWorkerNodeEligible(e){return this.isWorkerNodeReady(e)&&!this.hasWorkerNodeBackPressure(e)}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}checkNextWorkerNodeEligibility(){this.isWorkerNodeEligible(this.nextWorkerNodeKey)||(this.nextWorkerNodeKey=void 0)}computeDefaultWorkerWeight(){let e=0;for(const t of s.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/s.cpus().length)}}class K extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:w,elu:{aggregate:!0,average:!0,median:!1}};constructor(e,t=p){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)}),t.strategyData.virtualTaskEndTimestamp<r[e].strategyData.virtualTaskEndTimestamp?s:e)),0)}computeWorkerNodeVirtualTaskEndTimestamp(e){return this.getWorkerNodeVirtualTaskEndTimestamp(e,this.getWorkerNodeVirtualTaskStartTimestamp(e))}getWorkerNodeVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===O.elu?this.getWorkerNodeTaskElu(e):this.getWorkerNodeTaskRunTime(e))}getWorkerNodeVirtualTaskStartTimestamp(e){const t=this.pool.workerNodes[e]?.strategyData?.virtualTaskEndTimestamp,s=performance.now();return s<(t??-1/0)?t:s}}class q extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:w,elu:w};roundId=0;defaultWorkerWeight;roundWeights;workerNodeId=0;workerNodeVirtualTaskRunTime=0;constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,this.workerNodeId=0,this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){for(let e=this.roundId;e<this.roundWeights.length;e++){this.roundId=e;for(let t=this.workerNodeId;t<this.pool.workerNodes.length;t++){this.workerNodeId=t,this.workerNodeId!==this.nextWorkerNodeKey&&0!==this.workerNodeVirtualTaskRunTime&&(this.workerNodeVirtualTaskRunTime=0);const s=this.opts.weights?.[t]??this.defaultWorkerWeight;if(s>=this.roundWeights[e]&&this.workerNodeVirtualTaskRunTime<s)return this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(t),this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=t,this.nextWorkerNodeKey}}this.interleavedWeightedRoundRobinNextWorkerNodeId()}interleavedWeightedRoundRobinNextWorkerNodeId(){this.roundId===this.roundWeights.length-1&&this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=0,this.workerNodeId=0):this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=this.roundId+1,this.workerNodeId=0):this.workerNodeId=this.workerNodeId+1}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.workerNodeId===e&&this.workerNodeId>this.pool.workerNodes.length-1&&(this.workerNodeId=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}setOptions(e){super.setOptions(e),this.roundWeights=this.getRoundWeights()}getRoundWeights(){return null==this.opts.weights?[this.defaultWorkerWeight]:[...new Set(Object.values(this.opts.weights).slice().sort(((e,t)=>e-t)))]}}class B extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:w};constructor(e,t=p){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)=>(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 U extends Q{constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>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 A extends Q{taskStatisticsRequirements={runTime:w,waitTime:w,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=p){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)=>(t.usage.elu.active.aggregate??0)<(r[e].usage.elu.active.aggregate??0)?s:e),0)}}class D extends Q{constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.setPreviousWorkerNodeKey(e),this.roundRobinNextWorkerNodeKey(),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 L extends Q{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:w,elu:w};defaultWorkerWeight;workerNodeVirtualTaskRunTime=0;constructor(e,t=p){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.weightedRoundRobinNextWorkerNodeKey()}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&(this.workerNodeVirtualTaskRunTime=0,this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight;return this.workerNodeVirtualTaskRunTime<e?this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerNodeVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class _{workerChoiceStrategy;opts;workerChoiceStrategies;retriesCount=0;constructor(e,t=C.ROUND_ROBIN,s=p){this.workerChoiceStrategy=t,this.opts=s,this.opts={...p,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[C.ROUND_ROBIN,new(D.bind(this))(e,s)],[C.LEAST_USED,new(U.bind(this))(e,s)],[C.LEAST_BUSY,new(B.bind(this))(e,s)],[C.LEAST_ELU,new(A.bind(this))(e,s)],[C.FAIR_SHARE,new(K.bind(this))(e,s)],[C.WEIGHTED_ROUND_ROBIN,new(L.bind(this))(e,s)],[C.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(q.bind(this))(e,s)]])}getStrategyPolicy(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).strategyPolicy}getTaskStatisticsRequirements(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).taskStatisticsRequirements}setWorkerChoiceStrategy(e){this.workerChoiceStrategy!==e&&(this.workerChoiceStrategy=e),this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()}update(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).update(e)}execute(){const e=this.workerChoiceStrategies.get(this.workerChoiceStrategy).choose();if(null==e&&this.retriesCount<this.opts.retries)return this.retriesCount++,this.execute();if(null==e)throw new Error(`Worker node key chosen is null or undefined after ${this.retriesCount} retries`);return this.retriesCount=0,e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...p,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class j extends Array{size;constructor(e=1024,...t){super(),this.checkSize(e),this.size=e,arguments.length>1&&this.push(...t)}push(...e){const t=super.push(...e);return t>this.size&&super.splice(0,t-this.size),this.length}unshift(...e){return super.unshift(...e)>this.size&&super.splice(this.size,e.length),this.length}concat(...e){const t=super.concat(e);return t.size=this.size,t.length>t.size&&t.splice(0,t.length-t.size),t}splice(e,t,...s){let r=[];if(arguments.length>=3&&null!=t){if(r=super.splice(e,t,...s),this.length>this.size){const e=super.splice(0,this.length-this.size);r=new j(r.length+e.length,...r,...e)}}else r=2===arguments.length?super.splice(e,t):super.splice(e);return r}resize(e){if(this.checkSize(e),0===e)this.length=0;else if(e<this.size)for(let t=e;t<this.size;t++)super.pop();this.size=e}empty(){return 0===this.length}full(){return this.length===this.size}checkSize(e){if(!Number.isSafeInteger(e))throw new TypeError(`Invalid circular array size: ${e} is not a safe integer`);if(e<0)throw new RangeError(`Invalid circular array size: ${e} < 0`)}}class H{data;next;prev;constructor(e){this.data=e}}class V{head;tail;size;maxSize;constructor(){this.clear()}push(e){const t=new H(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 H(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?this.head=void 0:this.tail.next=void 0,--this.size,e?.data}shift(){if(null==this.head)return;const e=this.head;return this.head=this.head.next,null==this.head?this.tail=void 0:this.head.prev=void 0,--this.size,e?.data}peekFirst(){return this.head?.data}peekLast(){return this.tail?.data}clear(){this.head=void 0,this.tail=void 0,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 ${worker;info;usage;strategyData;messageChannel;tasksQueueBackPressureSize;onBackPressure;onEmptyQueue;tasksQueue;onBackPressureStarted;onEmptyQueueCount;taskFunctionsUsage;constructor(e,t){((e,t)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker");if(null==t)throw new TypeError("Cannot construct a worker node without a tasks queue back pressure size");if(!Number.isSafeInteger(t))throw new TypeError("Cannot construct a worker node with a tasks queue back pressure size that is not an integer");if(t<=0)throw new RangeError("Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer")})(e,t),this.worker=e,this.info=this.initWorkerInfo(e),this.usage=this.initWorkerUsage(),this.info.type===l.thread&&(this.messageChannel=new o.MessageChannel),this.tasksQueueBackPressureSize=t,this.tasksQueue=new V,this.onBackPressureStarted=!1,this.onEmptyQueueCount=0,this.taskFunctionsUsage=new Map}tasksQueueSize(){return this.tasksQueue.size}enqueueTask(e){const t=this.tasksQueue.push(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}unshiftTask(e){const t=this.tasksQueue.unshift(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}dequeueTask(){const e=this.tasksQueue.shift();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(m),e}popTask(){const e=this.tasksQueue.pop();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(m),e}clearTasksQueue(){this.tasksQueue.clear()}hasBackPressure(){return this.tasksQueue.size>=this.tasksQueueBackPressureSize}resetUsage(){this.usage=this.initWorkerUsage(),this.taskFunctionsUsage.clear()}closeChannel(){null!=this.messageChannel&&(this.messageChannel?.port1.unref(),this.messageChannel?.port2.unref(),this.messageChannel?.port1.close(),this.messageChannel?.port2.close(),delete this.messageChannel)}getTaskFunctionWorkerUsage(e){if(!Array.isArray(this.info.taskFunctionNames))throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list is not yet defined`);if(Array.isArray(this.info.taskFunctionNames)&&this.info.taskFunctionNames.length<3)throw new Error(`Cannot get task function worker usage for task function name '${e}' when task function names list has less than 3 elements`);return e===g&&(e=this.info.taskFunctionNames[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}deleteTaskFunctionWorkerUsage(e){return this.taskFunctionsUsage.delete(e)}async startOnEmptyQueue(){this.onEmptyQueueCount>0&&(this.usage.tasks.executing>0||this.tasksQueue.size>0)?this.onEmptyQueueCount=0:(++this.onEmptyQueueCount,this.onEmptyQueue?.(this.info.id),await(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()})(this.onEmptyQueueCount)),await this.startOnEmptyQueue())}initWorkerInfo(e){return{id:T(e),type:y(e),dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueue.size,t=()=>this.tasksQueue.maxSize;return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},stolen:0,failed:0},runTime:{history:new j},waitTime:{history:new j},elu:{idle:{history:new j},active:{history:new j}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===g&&e===this.info.taskFunctionNames[1]||s.name!==g&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},stolen:0,failed:0},runTime:{history:new j},waitTime:{history:new j},elu:{idle:{history:new j},active:{history:new j}}}}}class G{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;taskFunctions;started;starting;startTimestamp;constructor(e,s,r){if(this.numberOfWorkers=e,this.filePath=s,this.opts=r,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");(e=>{if(null==e||"string"!=typeof e||"string"==typeof e&&0===e.trim().length)throw new Error("Please specify a file with a worker implementation");if(!t.existsSync(e))throw new Error(`Cannot find the worker file '${e}'`)})(this.filePath),this.checkNumberOfWorkers(this.numberOfWorkers),this.checkPoolOptions(this.opts),this.chooseWorkerNode=this.chooseWorkerNode.bind(this),this.executeTask=this.executeTask.bind(this),this.enqueueTask=this.enqueueTask.bind(this),!0===this.opts.enableEvents&&(this.emitter=new c),this.workerChoiceStrategyContext=new _(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.taskFunctions=new Map,this.started=!1,this.starting=!1,!0===this.opts.startWorkers&&this.start(),this.startTimestamp=n.performance.now()}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new TypeError("Cannot instantiate a pool with a non safe integer number of workers");if(e<0)throw new RangeError("Cannot instantiate a pool with a negative number of workers");if(this.type===k.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkPoolOptions(e){if(!S(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.startWorkers=e.startWorkers??!0,R(e.workerChoiceStrategy),this.opts.workerChoiceStrategy=e.workerChoiceStrategy??C.ROUND_ROBIN,this.checkValidWorkerChoiceStrategyOptions(e.workerChoiceStrategyOptions),this.opts.workerChoiceStrategyOptions={...p,...e.workerChoiceStrategyOptions},this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(z(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategyOptions(e){if(null!=e&&!S(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e?.retries&&!Number.isSafeInteger(e.retries))throw new TypeError("Invalid worker choice strategy options: retries must be an integer");if(null!=e?.retries&&e.retries<0)throw new RangeError(`Invalid worker choice strategy options: retries '${e.retries}' must be greater or equal than zero`);if(null!=e?.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e?.measurement&&!Object.values(O).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}get info(){return{version:"2.7.2",type:this.type,worker:this.worker,started:this.started,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:W(this.utilization)},workerNodes:this.workerNodes.length,idleWorkerNodes:this.workerNodes.reduce(((e,t)=>0===t.usage.tasks.executing?e+1:e),0),busyWorkerNodes:this.workerNodes.reduce(((e,t)=>t.usage.tasks.executing>0?e+1:e),0),executedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executed),0),executingTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executing),0),...!0===this.opts.enableTasksQueue&&{queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0)},...!0===this.opts.enableTasksQueue&&{maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.maxQueued??0)),0)},...!0===this.opts.enableTasksQueue&&{backPressure:this.hasBackPressure()},...!0===this.opts.enableTasksQueue&&{stolenTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.stolen),0)},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:W(b(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:W(I(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&{average:W(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:W(N(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:W(b(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:W(I(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&{average:W(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:W(N(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(n.performance.now()-this.startTimestamp)*this.maxSize;return(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)+this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0))/e}get minSize(){return this.numberOfWorkers}get maxSize(){return this.max??this.numberOfWorkers}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Worker message received without worker id");if(null!=e.workerId&&-1===this.getWorkerNodeKeyByWorkerId(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKeyByWorker(e){return this.workerNodes.findIndex((t=>t.worker===e))}getWorkerNodeKeyByWorkerId(e){return this.workerNodes.findIndex((t=>t.info.id===e))}setWorkerChoiceStrategy(e,t){R(e),this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(this.opts.workerChoiceStrategy),null!=t&&this.setWorkerChoiceStrategyOptions(t);for(const[e,t]of this.workerNodes.entries())t.resetUsage(),this.sendStatisticsMessageToWorker(e)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions={...p,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||(this.unsetTaskStealing(),this.unsetTasksStealingOnBackPressure(),this.flushTasksQueues()),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(z(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e),this.setTasksQueueSize(this.opts.tasksQueueOptions.size),!0===this.opts.tasksQueueOptions.taskStealing?this.setTaskStealing():this.unsetTaskStealing(),!0===this.opts.tasksQueueOptions.tasksStealingOnBackPressure?this.setTasksStealingOnBackPressure():this.unsetTasksStealingOnBackPressure()):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{size:Math.pow(this.maxSize,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,...e}}setTasksQueueSize(e){for(const t of this.workerNodes)t.tasksQueueBackPressureSize=e}setTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)}unsetTaskStealing(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onEmptyQueue}setTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)}unsetTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onBackPressure}get full(){return this.workerNodes.length>=this.maxSize}internalBusy(){return!0===this.opts.enableTasksQueue?-1===this.workerNodes.findIndex((e=>e.info.ready&&e.usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency)):-1===this.workerNodes.findIndex((e=>e.info.ready&&0===e.usage.tasks.executing))}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(((i,o)=>{if(!this.started)return void o(new Error("Cannot execute a task on not started pool"));if(null!=t&&"string"!=typeof t)return void o(new TypeError("name argument must be a string"));if(null!=t&&"string"==typeof t&&0===t.trim().length)return void o(new TypeError("name argument must not be an empty string"));if(null!=s&&!Array.isArray(s))return void o(new TypeError("transferList argument must be an array"));const a=n.performance.now(),u=this.chooseWorkerNode(),h={name:t??g,data:e??{},transferList:s,timestamp:a,taskId:r.randomUUID()};this.promiseResponseMap.set(h.taskId,{resolve:i,reject:o,workerNodeKey:u}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.shallExecuteTask(u)?this.executeTask(u,h):this.enqueueTask(u,h)}))}start(){for(this.starting=!0;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode();this.starting=!1,this.started=!0}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(d.destroy,this.info),this.started=!1}async sendKillMessageToWorker(e){await new Promise(((t,s)=>{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})}))}setupHook(){}beforeTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}}afterTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name);this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return null!=t&&Array.isArray(t.taskFunctionNames)&&t.taskFunctionNames.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;null!=s.executing&&s.executing>0&&--s.executing,null==t.workerError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){null==t.workerError&&P(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0)}updateWaitTimeWorkerUsage(e,t){const s=n.performance.now(),r=s-(t.timestamp??s);P(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r)}updateEluWorkerUsage(e,t){if(null!=t.workerError)return;const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;P(e.elu.active,s,t.taskPerformance?.elu?.active??0),P(e.elu.idle,s,t.taskPerformance?.elu?.idle??0),s.aggregate&&null!=t.taskPerformance?.elu&&(null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization)}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorkerNode();if(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===k.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorker();e.on("online",this.opts.onlineHandler??m),e.on("message",this.opts.messageHandler??m),e.on("error",this.opts.errorHandler??m),e.on("error",(t=>{const s=this.getWorkerNodeKeyByWorker(e),r=this.getWorkerInfo(s);r.ready=!1,this.workerNodes[s].closeChannel(),this.emitter?.emit(d.error,t),this.started&&!this.starting&&!0===this.opts.restartWorkerOnError&&(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),this.started&&!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(s)})),e.on("exit",this.opts.exitHandler??m),e.once("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;(x(M.HARD,e.kill)||x(M.SOFT,e.kill)&&(!1===this.opts.enableTasksQueue&&0===s.tasks.executing||!0===this.opts.enableTasksQueue&&0===s.tasks.executing&&0===this.tasksQueueSize(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.workerListener()),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e),!0===this.opts.enableTasksQueue&&(!0===this.opts.tasksQueueOptions?.taskStealing&&(this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)),!0===this.opts.tasksQueueOptions?.tasksStealingOnBackPressure&&(this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)))}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate}})}redistributeQueuedTasks(e){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),s=this.dequeueTask(e);this.shallExecuteTask(t)?this.executeTask(t,s):this.enqueueTask(t,s)}}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}}taskStealingOnEmptyQueue(e){const t=this.getWorkerNodeKeyByWorkerId(e),s=this.workerNodes.slice().sort(((e,t)=>t.usage.tasks.queued-e.usage.tasks.queued)).find((t=>t.info.ready&&t.info.id!==e&&t.usage.tasks.queued>0));if(null!=s){const e=s.popTask();this.shallExecuteTask(t)?this.executeTask(t,e):this.enqueueTask(t,e),this.updateTaskStolenStatisticsWorkerUsage(t,e.name)}}tasksStealingOnBackPressure(e){if(this.opts.tasksQueueOptions?.size<=1)return;const t=this.workerNodes[this.getWorkerNodeKeyByWorkerId(e)],s=this.workerNodes.slice().sort(((e,t)=>e.usage.tasks.queued-t.usage.tasks.queued));for(const[r,i]of s.entries())if(t.usage.tasks.queued>0&&i.info.ready&&i.info.id!==e&&i.usage.tasks.queued<this.opts.tasksQueueOptions?.size-1){const e=t.popTask();this.shallExecuteTask(r)?this.executeTask(r,e):this.enqueueTask(r,e),this.updateTaskStolenStatisticsWorkerUsage(r,e.name)}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctionNames?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctionNames&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctionNames=e.taskFunctionNames)}}handleWorkerReadyResponse(e){if(!1===e.ready)throw new Error(`Worker ${e.workerId} failed to initialize`);const t=this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId));t.ready=e.ready,t.taskFunctionNames=e.taskFunctionNames,this.ready&&this.emitter?.emit(d.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,workerError:s,data:r}=e,i=this.promiseResponseMap.get(t);if(null!=i){null!=s?(this.emitter?.emit(d.taskError,s),i.reject(s.message)):i.resolve(r);const o=i.workerNodeKey;this.afterTaskExecutionHook(o,e),this.workerChoiceStrategyContext.update(o),this.promiseResponseMap.delete(t),!0===this.opts.enableTasksQueue&&this.tasksQueueSize(o)>0&&this.workerNodes[o].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&this.executeTask(o,this.dequeueTask(o))}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(d.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(d.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===k.dynamic&&this.full&&this.emitter?.emit(d.full,this.info)}getWorkerInfo(e){return this.workerNodes[e].info}addWorkerNode(e){const t=new $(e,this.opts.tasksQueueOptions?.size??Math.pow(this.maxSize,2));this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker added not found in worker nodes");return s}removeWorkerNode(e){const t=this.getWorkerNodeKeyByWorker(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}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){for(;this.tasksQueueSize(e)>0;)this.executeTask(e,this.dequeueTask(e));this.workerNodes[e].clearTasksQueue()}flushTasksQueues(){for(const[e]of this.workerNodes.entries())this.flushTasksQueue(e)}}class Y extends G{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){i.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return i.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.once("exit",(()=>{e()}))}));t.once("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send({...t,workerId:this.workerNodes[e].info.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)}createWorker(){return i.fork(this.opts.env)}get type(){return k.fixed}get worker(){return l.cluster}get busy(){return this.internalBusy()}}class J extends G{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return o.isMainThread}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.once("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage({...t,workerId:this.workerNodes[e].info.id},s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e],s=t.messageChannel.port2;t.worker.postMessage({ready:!1,workerId:t.info.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)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV,...this.opts.workerOptions})}get type(){return k.fixed}get worker(){return l.thread}get busy(){return this.internalBusy()}}const X=(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")},Z=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")},ee=6e4,te={killBehavior:M.SOFT,maxInactiveTime:ee,killHandler:m};class se extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=te){if(super(e),this.isMain=t,this.mainWorker=s,this.opts=i,null==this.isMain)throw new Error("isMain parameter is mandatory");this.checkTaskFunctions(r),this.checkWorkerOptions(this.opts),this.isMain||this.getMainWorker().on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){(e=>{if(null!=e&&!S(e))throw new TypeError("opts worker options parameter is not a plain object");if(null!=e?.killBehavior&&!Object.values(M).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");if(null!=e?.async)throw new Error("async option is deprecated")})(e),this.opts={...te,...e}}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e){const t=e.bind(this);this.taskFunctions.set(g,t),this.taskFunctions.set("string"==typeof e.name&&e.name.trim().length>0?e.name:"fn1",t)}else{if(!S(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){X(s,r);const e=r.bind(this);t&&(this.taskFunctions.set(g,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){try{Z(e)}catch(e){return{status:!1,error:e}}return{status:this.taskFunctions.has(e)}}addTaskFunction(e,t){try{if(Z(e),e===g)throw new Error("Cannot add a task function with the default reserved name");if("function"!=typeof t)throw new TypeError("fn parameter is not a function");const s=t.bind(this);return this.taskFunctions.get(e)===this.taskFunctions.get(g)&&this.taskFunctions.set(g,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(Z(e),e===g)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(g))throw new Error("Cannot remove the task function used as the default task function");const t=this.taskFunctions.delete(e);return this.sendTaskFunctionNamesToMainWorker(),{status:t}}catch(e){return{status:!1,error:e}}}listTaskFunctionNames(){const e=[...this.taskFunctions.keys()];let t=g;for(const[e,s]of this.taskFunctions)if(e!==g&&s===this.taskFunctions.get(g)){t=e;break}return[e[e.indexOf(g)],t,...e.filter((e=>e!==g&&e!==t))]}setDefaultTaskFunction(e){try{if(Z(e),e===g)throw new Error("Cannot set the default task function reserved name as the default task function");if(!this.taskFunctions.has(e))throw new Error("Cannot set the default task function to a non-existing task function");return this.taskFunctions.set(g,this.taskFunctions.get(e)),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskFunctionOperation?this.handleTaskFunctionOperationMessage(e):null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleTaskFunctionOperationMessage(e){const{taskFunctionOperation:t,taskFunctionName:s,taskFunction:r}=e;let i;switch(t){case"add":i=this.addTaskFunction(s,new Function(`return ${r}`)());break;case"remove":i=this.removeTaskFunction(s);break;case"default":i=this.setDefaultTaskFunction(s);break;default:i={status:!1,error:new Error("Unknown task operation")}}this.sendToMainWorker({taskFunctionOperation:t,taskFunctionOperationStatus:i.status,taskFunctionName:s,...!i.status&&null!=i?.error&&{workerError:{name:s,message:this.handleError(i.error)}}})}handleKillMessage(e){if(this.stopCheckActive(),E(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>(this.sendToMainWorker({kill:"success"}),null))).catch((()=>{this.sendToMainWorker({kill:"failure"})})).finally((()=>{this.emitDestroy()})).catch(m);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success"})}catch{this.sendToMainWorker({kill:"failure"})}finally{this.emitDestroy()}}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Message worker id is not set");if(null!=e.workerId&&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??ee)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){n.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??ee)&&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=this.taskFunctions.get(t??g);null!=i?E(i)?this.runInAsyncScope(this.runAsync.bind(this),this,i,e):this.runInAsyncScope(this.runSync.bind(this),this,i,e):this.sendToMainWorker({workerError:{name:t,message:`Task function '${t}' not found`,data:r},taskId:s})}runSync(e,t){const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,taskId:r})}catch(e){this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})}finally{this.updateLastTaskTimestamp()}}runAsync(e,t){const{name:s,taskId:r,data:i}=t;let o=this.beginTaskPerformance(s);e(i).then((e=>{o=this.endTaskPerformance(o),this.sendToMainWorker({data:e,taskPerformance:o,taskId:r})})).catch((e=>{this.sendToMainWorker({workerError:{name:s,message:this.handleError(e),data:i},taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(m)}beginTaskPerformance(e){return this.checkStatistics(),{name:e??g,timestamp:n.performance.now(),...this.statistics.elu&&{elu:n.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:n.performance.now()-e.timestamp},...this.statistics.elu&&{elu:n.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=n.performance.now())}}exports.ClusterWorker=class extends se{constructor(e,t={}){super("worker-cluster-pool:poolifier",i.isPrimary,i.worker,e,t)}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 Y{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,F(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends J{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,F(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=Y,exports.FixedThreadPool=J,exports.KillBehaviors=M,exports.Measurements=O,exports.PoolEvents=d,exports.PoolTypes=k,exports.ThreadWorker=class extends se{port;constructor(e,t={}){super("worker-thread-pool:poolifier",o.isMainThread,o.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 o.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=h.availableParallelism()}catch{const t=h.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
"use strict";var e=require("node:fs"),t=require("node:os"),s=require("node:crypto"),r=require("node:cluster"),i=require("node:worker_threads"),o=require("node:perf_hooks"),n=require("node:events"),a=require("node:async_hooks");function u(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 h=u(t);const k=Object.freeze({fixed:"fixed",dynamic:"dynamic"}),c=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),d=Object.freeze({thread:"thread",cluster:"cluster"}),l="default",g=Object.freeze((()=>{})),m={retries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},p={aggregate:!1,average:!1,median:!1},w=e=>e instanceof i.Worker?d.thread:e instanceof r.Worker?d.cluster:void 0,y=e=>e instanceof i.Worker?e.threadId:e instanceof r.Worker?e.id:void 0,T=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,f=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,E=()=>s.webcrypto.getRandomValues(new Uint32Array(1))[0]/4294967296,v=(...e)=>e.reduce(((e,t)=>e<t?e:t),1/0),b=(...e)=>e.reduce(((e,t)=>e>t?e:t),-1/0),I=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"}),C=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"}),O=(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")},F=e=>{if(null!=e&&!Object.values(I).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)},R=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`)},z=(e,t,s)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=v(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=T(e.history):null!=e.average&&delete e.average,t.median?e.median=f(e.history):null!=e.median&&delete e.median))},P=Object.freeze({SOFT:"SOFT",HARD:"HARD"});class M{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:p,waitTime:p,elu:p};constructor(e,t=m){this.pool=e,this.opts=t,this.opts={...m,...t},this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.runTime,e.runTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.waitTime,e.waitTime?.median),this.toggleMedianMeasurementStatisticsRequirements(this.taskStatisticsRequirements.elu,e.elu?.median)}toggleMedianMeasurementStatisticsRequirements(e,t){e.average&&t&&(e.average=!1,e.median=t),e.median&&!t&&(e.average=!0,e.median=t)}resetWorkerNodeKeyProperties(){this.nextWorkerNodeKey=0,this.previousWorkerNodeKey=0}setOptions(e){this.opts={...m,...e},this.setTaskStatisticsRequirements(this.opts)}isWorkerNodeReady(e){return this.pool.workerNodes[e].info.ready}hasWorkerNodeBackPressure(e){return this.pool.hasWorkerNodeBackPressure(e)}isWorkerNodeEligible(e){return this.isWorkerNodeReady(e)&&!this.hasWorkerNodeBackPressure(e)}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}checkNextWorkerNodeEligibility(){this.isWorkerNodeEligible(this.nextWorkerNodeKey)||(this.nextWorkerNodeKey=void 0)}computeDefaultWorkerWeight(){let e=0;for(const s of t.cpus()){const t=s.speed.toString().length-1;e+=1/(s.speed/Math.pow(10,t))*Math.pow(10,t)}return Math.round(e/t.cpus().length)}}class Q extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:{aggregate:!0,average:!0,median:!1}};constructor(e,t=m){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)}),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===C.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 K extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};roundId=0;defaultWorkerWeight;roundWeights;workerNodeId=0;workerNodeVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,this.workerNodeId=0,this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){for(let e=this.roundId;e<this.roundWeights.length;e++){this.roundId=e;for(let t=this.workerNodeId;t<this.pool.workerNodes.length;t++){this.workerNodeId=t,this.workerNodeId!==this.nextWorkerNodeKey&&0!==this.workerNodeVirtualTaskRunTime&&(this.workerNodeVirtualTaskRunTime=0);const s=this.opts.weights?.[t]??this.defaultWorkerWeight;if(s>=this.roundWeights[e]&&this.workerNodeVirtualTaskRunTime<s)return this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(t),this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=t,this.nextWorkerNodeKey}}this.interleavedWeightedRoundRobinNextWorkerNodeId()}interleavedWeightedRoundRobinNextWorkerNodeId(){this.roundId===this.roundWeights.length-1&&this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=0,this.workerNodeId=0):this.workerNodeId===this.pool.workerNodes.length-1?(this.roundId=this.roundId+1,this.workerNodeId=0):this.workerNodeId=this.workerNodeId+1}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.workerNodeId===e&&this.workerNodeId>this.pool.workerNodes.length-1&&(this.workerNodeId=this.pool.workerNodes.length-1),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}setOptions(e){super.setOptions(e),this.roundWeights=this.getRoundWeights()}getRoundWeights(){return null==this.opts.weights?[this.defaultWorkerWeight]:[...new Set(Object.values(this.opts.weights).slice().sort(((e,t)=>e-t)))]}}class q extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:p};constructor(e,t=m){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)=>(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 B extends M{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){return this.pool.workerNodes.reduce(((e,t,s,r)=>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 A extends M{taskStatisticsRequirements={runTime:p,waitTime:p,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=m){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)=>(t.usage.elu.active.aggregate??0)<(r[e].usage.elu.active.aggregate??0)?s:e),0)}}class U extends M{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.setPreviousWorkerNodeKey(e),this.roundRobinNextWorkerNodeKey(),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 D extends M{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};defaultWorkerWeight;workerNodeVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerNodeVirtualTaskRunTime=0,!0}update(){return!0}choose(){return this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey),this.weightedRoundRobinNextWorkerNodeKey()}remove(e){return 0===this.pool.workerNodes.length&&this.reset(),this.nextWorkerNodeKey===e&&(this.workerNodeVirtualTaskRunTime=0,this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),this.previousWorkerNodeKey===e&&this.previousWorkerNodeKey>this.pool.workerNodes.length-1&&(this.previousWorkerNodeKey=this.pool.workerNodes.length-1),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight;return this.workerNodeVirtualTaskRunTime<e?this.workerNodeVirtualTaskRunTime=this.workerNodeVirtualTaskRunTime+this.getWorkerNodeTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerNodeVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class L{workerChoiceStrategy;opts;workerChoiceStrategies;retriesCount=0;constructor(e,t=I.ROUND_ROBIN,s=m){this.workerChoiceStrategy=t,this.opts=s,this.opts={...m,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[I.ROUND_ROBIN,new(U.bind(this))(e,s)],[I.LEAST_USED,new(B.bind(this))(e,s)],[I.LEAST_BUSY,new(q.bind(this))(e,s)],[I.LEAST_ELU,new(A.bind(this))(e,s)],[I.FAIR_SHARE,new(Q.bind(this))(e,s)],[I.WEIGHTED_ROUND_ROBIN,new(D.bind(this))(e,s)],[I.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(K.bind(this))(e,s)]])}getStrategyPolicy(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).strategyPolicy}getTaskStatisticsRequirements(){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).taskStatisticsRequirements}setWorkerChoiceStrategy(e){this.workerChoiceStrategy!==e&&(this.workerChoiceStrategy=e),this.workerChoiceStrategies.get(this.workerChoiceStrategy)?.reset()}update(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).update(e)}execute(){const e=this.workerChoiceStrategies.get(this.workerChoiceStrategy).choose();if(null==e&&this.retriesCount<this.opts.retries)return this.retriesCount++,this.execute();if(null==e)throw new Error(`Worker node key chosen is null or undefined after ${this.retriesCount} retries`);return this.retriesCount=0,e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...m,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class _ 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 _(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 j{data;next;prev;constructor(e){this.data=e}}class H{head;tail;size;maxSize;constructor(){this.clear()}push(e){const t=new j(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 j(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?this.head=void 0:this.tail.next=void 0,--this.size,e?.data}shift(){if(null==this.head)return;const e=this.head;return this.head=this.head.next,null==this.head?this.tail=void 0:this.head.prev=void 0,--this.size,e?.data}peekFirst(){return this.head?.data}peekLast(){return this.tail?.data}clear(){this.head=void 0,this.tail=void 0,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 V{worker;info;usage;strategyData;messageChannel;tasksQueueBackPressureSize;onBackPressure;onEmptyQueue;tasksQueue;onBackPressureStarted;onEmptyQueueCount;taskFunctionsUsage;constructor(e,t){((e,t)=>{if(null==e)throw new TypeError("Cannot construct a worker node without a worker");if(null==t)throw new TypeError("Cannot construct a worker node without a tasks queue back pressure size");if(!Number.isSafeInteger(t))throw new TypeError("Cannot construct a worker node with a tasks queue back pressure size that is not an integer");if(t<=0)throw new RangeError("Cannot construct a worker node with a tasks queue back pressure size that is not a positive integer")})(e,t),this.worker=e,this.info=this.initWorkerInfo(e),this.usage=this.initWorkerUsage(),this.info.type===d.thread&&(this.messageChannel=new i.MessageChannel),this.tasksQueueBackPressureSize=t,this.tasksQueue=new H,this.onBackPressureStarted=!1,this.onEmptyQueueCount=0,this.taskFunctionsUsage=new Map}tasksQueueSize(){return this.tasksQueue.size}enqueueTask(e){const t=this.tasksQueue.push(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}unshiftTask(e){const t=this.tasksQueue.unshift(e);return null!=this.onBackPressure&&this.hasBackPressure()&&!this.onBackPressureStarted&&(this.onBackPressureStarted=!0,this.onBackPressure(this.info.id),this.onBackPressureStarted=!1),t}dequeueTask(){const e=this.tasksQueue.shift();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(g),e}popTask(){const e=this.tasksQueue.pop();return null!=this.onEmptyQueue&&0===this.tasksQueue.size&&0===this.onEmptyQueueCount&&this.startOnEmptyQueue().catch(g),e}clearTasksQueue(){this.tasksQueue.clear()}hasBackPressure(){return this.tasksQueue.size>=this.tasksQueueBackPressureSize}resetUsage(){this.usage=this.initWorkerUsage(),this.taskFunctionsUsage.clear()}closeChannel(){null!=this.messageChannel&&(this.messageChannel?.port1.unref(),this.messageChannel?.port2.unref(),this.messageChannel?.port1.close(),this.messageChannel?.port2.close(),delete this.messageChannel)}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===l&&(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)}async startOnEmptyQueue(){this.onEmptyQueueCount>0&&(this.usage.tasks.executing>0||this.tasksQueue.size>0)?this.onEmptyQueueCount=0:(++this.onEmptyQueueCount,this.onEmptyQueue?.(this.info.id),await(async e=>{await new Promise((t=>{setTimeout(t,e)}))})(((e=0,t=100)=>{const s=Math.pow(2,e)*t;return s+.2*s*E()})(this.onEmptyQueueCount)),await this.startOnEmptyQueue())}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()},stolen:0,failed:0},runTime:{history:new _},waitTime:{history:new _},elu:{idle:{history:new _},active:{history:new _}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===l&&e===this.info.taskFunctionNames[1]||s.name!==l&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},stolen:0,failed:0},runTime:{history:new _},waitTime:{history:new _},elu:{idle:{history:new _},active:{history:new _}}}}}class ${numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;taskFunctions;started;starting;startTimestamp;constructor(t,s,r){if(this.numberOfWorkers=t,this.filePath=s,this.opts=r,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");(t=>{if(null==t||"string"!=typeof t||"string"==typeof t&&0===t.trim().length)throw new Error("Please specify a file with a worker implementation");if(!e.existsSync(t))throw new Error(`Cannot find the worker file '${t}'`)})(this.filePath),this.checkNumberOfWorkers(this.numberOfWorkers),this.checkPoolOptions(this.opts),this.chooseWorkerNode=this.chooseWorkerNode.bind(this),this.executeTask=this.executeTask.bind(this),this.enqueueTask=this.enqueueTask.bind(this),!0===this.opts.enableEvents&&this.initializeEventEmitter(),this.workerChoiceStrategyContext=new L(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.taskFunctions=new Map,this.started=!1,this.starting=!1,!0===this.opts.startWorkers&&this.start(),this.startTimestamp=o.performance.now()}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new TypeError("Cannot instantiate a pool with a non safe integer number of workers");if(e<0)throw new RangeError("Cannot instantiate a pool with a negative number of workers");if(this.type===k.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,F(e.workerChoiceStrategy),this.opts.workerChoiceStrategy=e.workerChoiceStrategy??I.ROUND_ROBIN,this.checkValidWorkerChoiceStrategyOptions(e.workerChoiceStrategyOptions),this.opts.workerChoiceStrategyOptions={...m,...e.workerChoiceStrategyOptions},this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(R(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?.retries&&!Number.isSafeInteger(e.retries))throw new TypeError("Invalid worker choice strategy options: retries must be an integer");if(null!=e?.retries&&e.retries<0)throw new RangeError(`Invalid worker choice strategy options: retries '${e.retries}' must be greater or equal than zero`);if(null!=e?.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e?.measurement&&!Object.values(C).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}initializeEventEmitter(){this.emitter=new n.EventEmitterAsyncResource({name:`poolifier:${this.type}-${this.worker}-pool`})}get info(){return{version:"2.7.3",type:this.type,worker:this.worker,started:this.started,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization: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)=>t.usage.tasks.executing>0?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(v(...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(T(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:N(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.runTime.history)),[])))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:N(v(...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(T(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:N(f(this.workerNodes.reduce(((e,t)=>e.concat(t.usage.waitTime.history)),[])))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(o.performance.now()-this.startTimestamp)*this.maxSize;return(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)+this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0))/e}get minSize(){return this.numberOfWorkers}get maxSize(){return this.max??this.numberOfWorkers}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Worker message received without worker id");if(null!=e.workerId&&-1===this.getWorkerNodeKeyByWorkerId(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKeyByWorker(e){return this.workerNodes.findIndex((t=>t.worker===e))}getWorkerNodeKeyByWorkerId(e){return this.workerNodes.findIndex((t=>t.info.id===e))}setWorkerChoiceStrategy(e,t){F(e),this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(this.opts.workerChoiceStrategy),null!=t&&this.setWorkerChoiceStrategyOptions(t);for(const[e,t]of this.workerNodes.entries())t.resetUsage(),this.sendStatisticsMessageToWorker(e)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions={...m,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||(this.unsetTaskStealing(),this.unsetTasksStealingOnBackPressure(),this.flushTasksQueues()),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(R(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e),this.setTasksQueueSize(this.opts.tasksQueueOptions.size),!0===this.opts.tasksQueueOptions.taskStealing?this.setTaskStealing():this.unsetTaskStealing(),!0===this.opts.tasksQueueOptions.tasksStealingOnBackPressure?this.setTasksStealingOnBackPressure():this.unsetTasksStealingOnBackPressure()):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{size:Math.pow(this.maxSize,2),concurrency:1,taskStealing:!0,tasksStealingOnBackPressure:!0,...e}}setTasksQueueSize(e){for(const t of this.workerNodes)t.tasksQueueBackPressureSize=e}setTaskStealing(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)}unsetTaskStealing(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onEmptyQueue}setTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)}unsetTasksStealingOnBackPressure(){for(const[e]of this.workerNodes.entries())delete this.workerNodes[e].onBackPressure}get full(){return this.workerNodes.length>=this.maxSize}internalBusy(){return!0===this.opts.enableTasksQueue?-1===this.workerNodes.findIndex((e=>e.info.ready&&e.usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency)):-1===this.workerNodes.findIndex((e=>e.info.ready&&0===e.usage.tasks.executing))}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,r){return await new Promise(((i,n)=>{if(!this.started)return void n(new Error("Cannot execute a task on not started pool"));if(null!=t&&"string"!=typeof t)return void n(new TypeError("name argument must be a string"));if(null!=t&&"string"==typeof t&&0===t.trim().length)return void n(new TypeError("name argument must not be an empty string"));if(null!=r&&!Array.isArray(r))return void n(new TypeError("transferList argument must be an array"));const a=o.performance.now(),u=this.chooseWorkerNode(),h={name:t??l,data:e??{},transferList:r,timestamp:a,taskId:s.randomUUID()};this.promiseResponseMap.set(h.taskId,{resolve:i,reject:n,workerNodeKey:u}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.shallExecuteTask(u)?this.executeTask(u,h):this.enqueueTask(u,h)}))}start(){for(this.starting=!0;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode();this.starting=!1,this.started=!0}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(c.destroy,this.info),this.emitter instanceof n.EventEmitterAsyncResource&&this.emitter?.emitDestroy(),this.started=!1}async sendKillMessageToWorker(e){await new Promise(((t,s)=>{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})}))}setupHook(){}beforeTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}}afterTaskExecutionHook(e,t){if(null!=this.workerNodes[e]?.usage){const s=this.workerNodes[e].usage;this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}if(this.shallUpdateTaskFunctionWorkerUsage(e)&&null!=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name);this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return null!=t&&Array.isArray(t.taskFunctionNames)&&t.taskFunctionNames.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;null!=s.executing&&s.executing>0&&--s.executing,null==t.workerError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){null==t.workerError&&z(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0)}updateWaitTimeWorkerUsage(e,t){const s=o.performance.now(),r=s-(t.timestamp??s);z(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r)}updateEluWorkerUsage(e,t){if(null!=t.workerError)return;const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;z(e.elu.active,s,t.taskPerformance?.elu?.active??0),z(e.elu.idle,s,t.taskPerformance?.elu?.idle??0),s.aggregate&&null!=t.taskPerformance?.elu&&(null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization)}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorkerNode();if(this.workerChoiceStrategyContext.getStrategyPolicy().dynamicWorkerUsage)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===k.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorker();e.on("online",this.opts.onlineHandler??g),e.on("message",this.opts.messageHandler??g),e.on("error",this.opts.errorHandler??g),e.on("error",(t=>{const s=this.getWorkerNodeKeyByWorker(e),r=this.getWorkerInfo(s);r.ready=!1,this.workerNodes[s].closeChannel(),this.emitter?.emit(c.error,t),this.started&&!this.starting&&!0===this.opts.restartWorkerOnError&&(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),this.started&&!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(s)})),e.on("exit",this.opts.exitHandler??g),e.once("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(P.HARD,e.kill)||S(P.SOFT,e.kill)&&(!1===this.opts.enableTasksQueue&&0===s.tasks.executing||!0===this.opts.enableTasksQueue&&0===s.tasks.executing&&0===this.tasksQueueSize(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.workerListener()),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e),!0===this.opts.enableTasksQueue&&(!0===this.opts.tasksQueueOptions?.taskStealing&&(this.workerNodes[e].onEmptyQueue=this.taskStealingOnEmptyQueue.bind(this)),!0===this.opts.tasksQueueOptions?.tasksStealingOnBackPressure&&(this.workerNodes[e].onBackPressure=this.tasksStealingOnBackPressure.bind(this)))}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate}})}redistributeQueuedTasks(e){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),s=this.dequeueTask(e);this.shallExecuteTask(t)?this.executeTask(t,s):this.enqueueTask(t,s)}}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}}taskStealingOnEmptyQueue(e){const t=this.getWorkerNodeKeyByWorkerId(e),s=this.workerNodes.slice().sort(((e,t)=>t.usage.tasks.queued-e.usage.tasks.queued)).find((t=>t.info.ready&&t.info.id!==e&&t.usage.tasks.queued>0));if(null!=s){const e=s.popTask();this.shallExecuteTask(t)?this.executeTask(t,e):this.enqueueTask(t,e),this.updateTaskStolenStatisticsWorkerUsage(t,e.name)}}tasksStealingOnBackPressure(e){if(this.opts.tasksQueueOptions?.size<=1)return;const t=this.workerNodes[this.getWorkerNodeKeyByWorkerId(e)],s=this.workerNodes.slice().sort(((e,t)=>e.usage.tasks.queued-t.usage.tasks.queued));for(const[r,i]of s.entries())if(t.usage.tasks.queued>0&&i.info.ready&&i.info.id!==e&&i.usage.tasks.queued<this.opts.tasksQueueOptions?.size-1){const e=t.popTask();this.shallExecuteTask(r)?this.executeTask(r,e):this.enqueueTask(r,e),this.updateTaskStolenStatisticsWorkerUsage(r,e.name)}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctionNames?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctionNames&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctionNames=e.taskFunctionNames)}}handleWorkerReadyResponse(e){if(!1===e.ready)throw new Error(`Worker ${e.workerId} failed to initialize`);const t=this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId));t.ready=e.ready,t.taskFunctionNames=e.taskFunctionNames,this.ready&&this.emitter?.emit(c.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,workerError:s,data:r}=e,i=this.promiseResponseMap.get(t);if(null!=i){null!=s?(this.emitter?.emit(c.taskError,s),i.reject(s.message)):i.resolve(r);const o=i.workerNodeKey;this.afterTaskExecutionHook(o,e),this.workerChoiceStrategyContext.update(o),this.promiseResponseMap.delete(t),!0===this.opts.enableTasksQueue&&this.tasksQueueSize(o)>0&&this.workerNodes[o].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&this.executeTask(o,this.dequeueTask(o))}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(c.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(c.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===k.dynamic&&this.full&&this.emitter?.emit(c.full,this.info)}getWorkerInfo(e){return this.workerNodes[e].info}addWorkerNode(e){const t=new V(e,this.opts.tasksQueueOptions?.size??Math.pow(this.maxSize,2));this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker added not found in worker nodes");return s}removeWorkerNode(e){const t=this.getWorkerNodeKeyByWorker(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}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){for(;this.tasksQueueSize(e)>0;)this.executeTask(e,this.dequeueTask(e));this.workerNodes[e].clearTasksQueue()}flushTasksQueues(){for(const[e]of this.workerNodes.entries())this.flushTasksQueue(e)}}class G extends ${opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){r.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return r.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.once("exit",(()=>{e()}))}));t.once("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send({...t,workerId:this.workerNodes[e].info.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)}createWorker(){return r.fork(this.opts.env)}get type(){return k.fixed}get worker(){return d.cluster}get busy(){return this.internalBusy()}}class Y extends ${opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return i.isMainThread}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.once("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage({...t,workerId:this.workerNodes[e].info.id},s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e],s=t.messageChannel.port2;t.worker.postMessage({ready:!1,workerId:t.info.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)}createWorker(){return new i.Worker(this.filePath,{env:i.SHARE_ENV,...this.opts.workerOptions})}get type(){return k.fixed}get worker(){return d.thread}get busy(){return this.internalBusy()}}const J=(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")},X=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")},Z=6e4,ee={killBehavior:P.SOFT,maxInactiveTime:Z,killHandler:g};class te extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=ee){if(super(e),this.isMain=t,this.mainWorker=s,this.opts=i,null==this.isMain)throw new Error("isMain parameter is mandatory");this.checkTaskFunctions(r),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(P).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");if(null!=e?.async)throw new Error("async option is deprecated")})(e),this.opts={...ee,...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(l,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)){J(s,r);const e=r.bind(this);t&&(this.taskFunctions.set(l,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){try{X(e)}catch(e){return{status:!1,error:e}}return{status:this.taskFunctions.has(e)}}addTaskFunction(e,t){try{if(X(e),e===l)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(l)&&this.taskFunctions.set(l,s),this.taskFunctions.set(e,s),this.sendTaskFunctionNamesToMainWorker(),{status:!0}}catch(e){return{status:!1,error:e}}}removeTaskFunction(e){try{if(X(e),e===l)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(l))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=l;for(const[e,s]of this.taskFunctions)if(e!==l&&s===this.taskFunctions.get(l)){t=e;break}return[e[e.indexOf(l)],t,...e.filter((e=>e!==l&&e!==t))]}setDefaultTaskFunction(e){try{if(X(e),e===l)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(l,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"}),null))).catch((()=>{this.sendToMainWorker({kill:"failure"})})).finally((()=>{this.emitDestroy()})).catch(g);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success"})}catch{this.sendToMainWorker({kill:"failure"})}finally{this.emitDestroy()}}checkMessageWorkerId(e){if(null==e.workerId)throw new Error("Message worker id is not set");if(null!=e.workerId&&e.workerId!==this.id)throw new Error(`Message worker id ${e.workerId} does not match the worker id ${this.id}`)}startCheckActive(){this.lastTaskTimestamp=o.performance.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??Z)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){o.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??Z)&&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=this.taskFunctions.get(t??l);null!=i?x(i)?this.runInAsyncScope(this.runAsync.bind(this),this,i,e):this.runInAsyncScope(this.runSync.bind(this),this,i,e):this.sendToMainWorker({workerError:{name:t,message:`Task function '${t}' not found`,data:r},taskId:s})}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??l,timestamp:o.performance.now(),...this.statistics.elu&&{elu:o.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:o.performance.now()-e.timestamp},...this.statistics.elu&&{elu:o.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=o.performance.now())}}exports.ClusterWorker=class extends te{constructor(e,t={}){super("poolifier:cluster-worker",r.isPrimary,r.worker,e,t)}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 G{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,O(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends Y{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,O(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=G,exports.FixedThreadPool=Y,exports.KillBehaviors=P,exports.Measurements=C,exports.PoolEvents=c,exports.PoolTypes=k,exports.ThreadWorker=class extends te{port;constructor(e,t={}){super("poolifier:thread-worker",i.isMainThread,i.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 i.threadId}sendToMainWorker(e){this.port.postMessage({...e,workerId:this.id})}handleError(e){return e}},exports.WorkerChoiceStrategies=I,exports.WorkerTypes=d,exports.availableParallelism=()=>{let e=1;try{e=h.availableParallelism()}catch{const t=h.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
//# sourceMappingURL=index.js.map
{
"$schema": "https://json.schemastore.org/package",
"name": "poolifier",
"version": "2.7.2",
"version": "2.7.3",
"description": "Fast and small Node.js Worker_Threads and Cluster Worker Pool",

@@ -93,3 +93,3 @@ "license": "MIT",

"@rollup/plugin-typescript": "^11.1.3",
"@types/node": "^20.6.3",
"@types/node": "^20.6.4",
"@typescript-eslint/eslint-plugin": "^6.7.2",

@@ -101,3 +101,3 @@ "@typescript-eslint/parser": "^6.7.2",

"eslint-config-standard": "^17.1.0",
"eslint-config-standard-with-typescript": "^39.0.0",
"eslint-config-standard-with-typescript": "^39.1.0",
"eslint-define-config": "^1.23.0",

@@ -118,4 +118,4 @@ "eslint-import-resolver-typescript": "^3.6.1",

"prettier": "^3.0.3",
"release-it": "^16.1.5",
"rollup": "^3.29.2",
"release-it": "^16.2.0",
"rollup": "^3.29.3",
"rollup-plugin-analyzer": "^4.0.0",

@@ -122,0 +122,0 @@ "rollup-plugin-command": "^1.1.3",

@@ -5,27 +5,23 @@ <div align="center">

<h1 align="center">Node.js Worker_Threads and Cluster Worker Pool</h1>
<div align="center">
<p align="center">
<a href="https://github.com/poolifier/poolifier/graphs/commit-activity">
<img alt="GitHub commit activity (master)" src="https://img.shields.io/github/commit-activity/m/poolifier/poolifier/master"></a>
<a href="https://www.npmjs.com/package/poolifier">
<img alt="Weekly Downloads" src="https://img.shields.io/npm/dw/poolifier"></a>
<a href="https://github.com/poolifier/poolifier/actions/workflows/ci.yml">
<img alt="Actions Status" src="https://github.com/poolifier/poolifier/actions/workflows/ci.yml/badge.svg"></a>
<a href="https://sonarcloud.io/dashboard?id=pioardi_poolifier">
<img alt="Code Coverage" src="https://sonarcloud.io/api/project_badges/measure?project=pioardi_poolifier&metric=coverage"></a>
<a href="https://sonarcloud.io/dashboard?id=pioardi_poolifier">
<img alt="Quality Gate Status" src="https://sonarcloud.io/api/project_badges/measure?project=pioardi_poolifier&metric=alert_status"></a>
<a href="https://standardjs.com">
<img alt="Javascript Standard Style Guide" src="https://img.shields.io/badge/code_style-standard-brightgreen.svg"></a>
<a href="https://gitter.im/poolifier/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge">
<img alt="Gitter chat" src="https://badges.gitter.im/poolifier/community.svg"></a>
<a href="https://opencollective.com/poolifier">
<img alt="Open Collective" src="https://opencollective.com/poolifier/tiers/badge.svg"></a>
<a href="http://makeapullrequest.com">
<img alt="PR Welcome" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square"></a>
<a href="https://img.shields.io/static/v1?label=dependencies&message=no%20dependencies&color=brightgreen">
<img alt="No dependencies" src="https://img.shields.io/static/v1?label=dependencies&message=no%20dependencies&color=brightgreen"></a>
</p>
# Node.js Worker_Threads and Cluster Worker Pool
</div>
<div align="center">
[![GitHub commit activity (master)](https://img.shields.io/github/commit-activity/m/poolifier/poolifier/master?color=brightgreen&logo=github)](https://github.com/poolifier/poolifier/graphs/commit-activity)
[![Weekly Downloads](https://badgen.net/npm/dw/poolifier?icon=npm)](https://www.npmjs.com/package/poolifier)
[![CI Workflow](https://github.com/poolifier/poolifier/actions/workflows/ci.yml/badge.svg)](https://github.com/poolifier/poolifier/actions/workflows/ci.yml)
[![Code Coverage](https://sonarcloud.io/api/project_badges/measure?project=pioardi_poolifier&metric=coverage)](https://sonarcloud.io/dashboard?id=pioardi_poolifier)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=pioardi_poolifier&metric=alert_status)](https://sonarcloud.io/dashboard?id=pioardi_poolifier)
[![Javascript Standard Style Guide](<https://badgen.net/static/code style/standard/green>)](https://standardjs.com)
[![Discord](https://badgen.net/discord/online-members/85VrP8m8?icon=discord&label=discord&color=green)](https://discord.gg/85VrP8m8)
[![Open Collective](https://opencollective.com/poolifier/tiers/badge.svg)](https://opencollective.com/poolifier)
[![PRs Welcome](https://badgen.net/static/PRs/welcome/green)](http://makeapullrequest.com)
[![No Dependencies](<https://badgen.net/static/dependencies/no dependencies/green>)](<https://badgen.net/static/dependencies/no dependencies/green>)
</div>
## Why Poolifier?

@@ -47,3 +43,3 @@

- Support for multiple task functions :white_check_mark:
- Support for task functions CRUD operations at runtime :white_check_mark:
- Support for task functions [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations at runtime :white_check_mark:
- Support for sync and async task functions :white_check_mark:

@@ -50,0 +46,0 @@ - Tasks distribution strategies :white_check_mark:

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc