poolifier 2.6.30 → 2.6.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("node:events"),t=require("node:worker_threads"),s=require("node:cluster"),r=require("node:crypto"),i=require("node:perf_hooks"),o=require("node:fs"),n=require("node:os"),a=require("node:async_hooks");function h(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var u=h(n);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="default",g=Object.freeze((()=>{})),m={choiceRetries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},p={aggregate:!1,average:!1,median:!1},w=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},y=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},f=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),T=(e,t)=>t===e,W=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,N=(e,t,s,r)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=Math.min(s,e.minimum??1/0),e.maximum=Math.max(s,e.maximum??-1/0),t.average&&0!==r&&(e.average=e.aggregate/r),t.median&&null!=s&&(e.history.push(s),e.median=w(e.history)))},x=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),S=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"}),E=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class b{pool;opts;nextWorkerNodeKey=0;strategyPolicy={useDynamicWorker:!1};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)}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)}getWorkerTaskRunTime(e){return this.taskStatisticsRequirements.runTime.median?this.pool.workerNodes[e].usage.runTime?.median??0:this.pool.workerNodes[e].usage.runTime?.average??0}getWorkerTaskWaitTime(e){return this.taskStatisticsRequirements.waitTime.median?this.pool.workerNodes[e].usage.waitTime?.median??0:this.pool.workerNodes[e].usage.waitTime?.average??0}getWorkerTaskElu(e){return this.taskStatisticsRequirements.elu.median?this.pool.workerNodes[e].usage.elu.active?.median??0:this.pool.workerNodes[e].usage.elu.active?.average??0}computeDefaultWorkerWeight(){let e=0;for(const t of n.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/n.cpus().length)}}class I extends b{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:{aggregate:!0,average:!0,median:!1}};workersVirtualTaskEndTimestamp=[];constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.workersVirtualTaskEndTimestamp=[],!0}update(e){return this.computeWorkerVirtualTaskEndTimestamp(e),!0}choose(){return this.fairShareNextWorkerNodeKey()}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}fairShareNextWorkerNodeKey(){let e=1/0;for(const[t]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[t]&&this.computeWorkerVirtualTaskEndTimestamp(t);const s=this.workersVirtualTaskEndTimestamp[t];this.isWorkerNodeEligible(t)&&s<e&&(e=s,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===E.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class C extends b{strategyPolicy={useDynamicWorker:!0};roundId=0;roundWeights;defaultWorkerWeight;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.nextWorkerNodeKey=0,this.roundId=0,!0}update(){return!0}choose(){let e,t;for(let s=this.roundId;s<this.roundWeights.length;s++)for(let r=this.nextWorkerNodeKey;r<this.pool.workerNodes.length;r++){const i=this.opts.weights?.[r]??this.defaultWorkerWeight;if(this.isWorkerNodeEligible(r)&&i>=this.roundWeights[s]){e=s,t=r;break}}this.roundId=e??0,this.nextWorkerNodeKey=t??0;const s=this.nextWorkerNodeKey;return this.nextWorkerNodeKey===this.pool.workerNodes.length-1?(this.nextWorkerNodeKey=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeKey=this.nextWorkerNodeKey+1,s}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+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 R extends b{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.leastBusyNextWorkerNodeKey()}remove(){return!0}leastBusyNextWorkerNodeKey(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=(s.usage.runTime?.aggregate??0)+(s.usage.waitTime?.aggregate??0);if(this.isWorkerNodeEligible(t)&&0===r){this.nextWorkerNodeKey=t;break}this.isWorkerNodeEligible(t)&&r<e&&(e=r,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}}class v extends b{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.leastUsedNextWorkerNodeKey()}remove(){return!0}leastUsedNextWorkerNodeKey(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage.tasks,i=r.executed+r.executing+r.queued;if(this.isWorkerNodeEligible(t)&&0===i){this.nextWorkerNodeKey=t;break}this.isWorkerNodeEligible(t)&&i<e&&(e=i,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}}class O extends b{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.leastEluNextWorkerNodeKey()}remove(){return!0}leastEluNextWorkerNodeKey(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage,i=r.elu?.active?.aggregate??0;if(this.isWorkerNodeEligible(t)&&0===i){this.nextWorkerNodeKey=t;break}this.isWorkerNodeEligible(t)&&i<e&&(e=i,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}}class z extends b{strategyPolicy={useDynamicWorker:!0};constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.nextWorkerNodeKey=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;do{this.roundRobinNextWorkerNodeKey()}while(!this.isWorkerNodeEligible(this.nextWorkerNodeKey));return e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),!0}roundRobinNextWorkerNodeKey(){return this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:this.nextWorkerNodeKey+1,this.nextWorkerNodeKey}}class F extends b{strategyPolicy={useDynamicWorker:!0};taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.nextWorkerNodeKey=0,this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;do{this.weightedRoundRobinNextWorkerNodeKey()}while(!this.isWorkerNodeEligible(this.nextWorkerNodeKey));return e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.workerVirtualTaskRunTime;return e<(this.opts.weights?.[this.nextWorkerNodeKey]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=e+this.getWorkerTaskRunTime(this.nextWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:this.nextWorkerNodeKey+1,this.workerVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class M{workerChoiceStrategy;opts;workerChoiceStrategies;choiceRetriesCount=0;constructor(e,t=S.ROUND_ROBIN,s=m){this.workerChoiceStrategy=t,this.opts=s,this.opts={...m,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[S.ROUND_ROBIN,new(z.bind(this))(e,s)],[S.LEAST_USED,new(v.bind(this))(e,s)],[S.LEAST_BUSY,new(R.bind(this))(e,s)],[S.LEAST_ELU,new(O.bind(this))(e,s)],[S.FAIR_SHARE,new(I.bind(this))(e,s)],[S.WEIGHTED_ROUND_ROBIN,new(F.bind(this))(e,s)],[S.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(C.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.choiceRetriesCount<this.opts.choiceRetries)return this.choiceRetriesCount++,this.execute();if(null==e)throw new TypeError(`Worker node key chosen is null or undefined after ${this.choiceRetriesCount} retries`);return this.choiceRetriesCount=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 K 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 K(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 P{items;offset;size;maxSize;constructor(){this.clear()}enqueue(e){return this.items.push(e),++this.size,this.size>this.maxSize&&(this.maxSize=this.size),this.size}dequeue(){if(this.size<=0)return;const e=this.items[this.offset];return 2*++this.offset>=this.items.length&&(this.items=this.items.slice(this.offset),this.offset=0),--this.size,e}peek(){if(!(this.size<=0))return this.items[this.offset]}clear(){this.items=[],this.offset=0,this.size=0,this.maxSize=0}[Symbol.iterator](){const e=this.items;let t=this.offset;return{next:()=>{if(t>=e.length)return{value:void 0,done:!0};const s=e[t];return++t,{value:s,done:!1}}}}}const q=Object.freeze({thread:"thread",cluster:"cluster"});class Q{worker;info;messageChannel;usage;taskFunctionsUsage;tasksQueue;tasksQueueBackPressureSize;constructor(e,s,r){if(null==e)throw new Error("Cannot construct a worker node without a worker");if(null==s)throw new Error("Cannot construct a worker node without a worker type");if(null==r)throw new Error("Cannot construct a worker node without a pool maximum size");if(isNaN(r))throw new Error("Cannot construct a worker node with a NaN pool maximum size");this.worker=e,this.info=this.initWorkerInfo(e,s),s===q.thread&&(this.messageChannel=new t.MessageChannel),this.usage=this.initWorkerUsage(),this.taskFunctionsUsage=new Map,this.tasksQueue=new P,this.tasksQueueBackPressureSize=Math.pow(r,2)}tasksQueueSize(){return this.tasksQueue.size}tasksQueueMaxSize(){return this.tasksQueue.maxSize}enqueueTask(e){return this.tasksQueue.enqueue(e)}dequeueTask(){return this.tasksQueue.dequeue()}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.taskFunctions))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.taskFunctions)&&this.info.taskFunctions.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.taskFunctions[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}initWorkerInfo(e,t){return{id:this.getWorkerId(e,t),type:t,dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueueSize(),t=()=>this.tasksQueueMaxSize();return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},failed:0},runTime:{history:new K},waitTime:{history:new K},elu:{idle:{history:new K},active:{history:new K}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)s.name===e&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},failed:0},runTime:{history:new K},waitTime:{history:new K},elu:{idle:{history:new K},active:{history:new K}}}}getWorkerId(e,t){return t===q.thread?e.threadId:t===q.cluster?e.id:void 0}}class A{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;starting;startTimestamp;constructor(e,t,s){if(this.numberOfWorkers=e,this.filePath=t,this.opts=s,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),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 M(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.starting=!0,this.startPool(),this.starting=!1,this.startTimestamp=i.performance.now()}checkFilePath(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(!o.existsSync(e))throw new Error(`Cannot find the worker file '${e}'`)}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")}checkDynamicPoolSize(e,t){if(this.type===k.dynamic){if(null==t)throw new Error("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")}}checkPoolOptions(e){if(!f(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??S.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions={...m,...e.workerChoiceStrategyOptions},this.checkValidWorkerChoiceStrategyOptions(this.opts.workerChoiceStrategyOptions),this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(this.checkValidTasksQueueOptions(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategy(e){if(!Object.values(S).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!f(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.choiceRetries&&!Number.isSafeInteger(e.choiceRetries))throw new TypeError("Invalid worker choice strategy options: choice retries must be an integer");if(null!=e.choiceRetries&&e.choiceRetries<=0)throw new RangeError(`Invalid worker choice strategy options: choice retries '${e.choiceRetries}' must be greater 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(E).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(e){if(null!=e&&!f(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 tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new Error(`Invalid worker tasks concurrency: ${e.concurrency} is a negative integer or zero`)}startPool(){for(;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode()}get info(){return{version:"2.6.30",type:this.type,worker:this.worker,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:y(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()},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:y(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:y(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:y(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:y(w(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:y(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:y(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:y(this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:y(w(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(i.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){this.checkValidWorkerChoiceStrategy(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.flushTasksQueues(),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(this.checkValidTasksQueueOptions(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e)):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{concurrency:e?.concurrency??1}}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))}listTaskFunctions(){for(const e of this.workerNodes)if(Array.isArray(e.info.taskFunctions)&&e.info.taskFunctions.length>0)return e.info.taskFunctions;return[]}async execute(e,t,s){return await new Promise(((o,n)=>{null!=t&&"string"!=typeof t&&n(new TypeError("name argument must be a string")),null!=t&&"string"==typeof t&&0===t.trim().length&&n(new TypeError("name argument must not be an empty string")),null==s||Array.isArray(s)||n(new TypeError("transferList argument must be an array"));const a=i.performance.now(),h=this.chooseWorkerNode(),u=this.getWorkerInfo(h);null!=t&&Array.isArray(u.taskFunctions)&&!u.taskFunctions.includes(t)&&n(new Error(`Task function '${t}' is not registered in the pool`));const k={name:t??l,data:e??{},transferList:s,timestamp:a,workerId:u.id,taskId:r.randomUUID()};this.promiseResponseMap.set(k.taskId,{resolve:o,reject:n,workerNodeKey:h}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.workerNodes[h].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency?this.executeTask(h,k):this.enqueueTask(h,k)}))}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(d.destroy,this.info)}async sendKillMessageToWorker(e,t){await new Promise(((s,r)=>{this.registerWorkerMessageListener(e,(e=>{"success"===e.kill?s():"failure"===e.kill&&r(new Error(`Worker ${t} kill message handling failed`))})),this.sendToWorker(e,{kill:!0,workerId:t})}))}setupHook(){}beforeTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;if(++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t),this.shallUpdateTaskFunctionWorkerUsage(e)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}}afterTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;if(this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t),this.shallUpdateTaskFunctionWorkerUsage(e)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name??l);this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return Array.isArray(t.taskFunctions)&&t.taskFunctions.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;if(null!=s.executing&&s.executing>0)--s.executing;else if(null!=s.executing&&s.executing<0)throw new Error("Worker usage statistic for tasks executing cannot be negative");null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){N(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0,e.tasks.executed)}updateWaitTimeWorkerUsage(e,t){const s=i.performance.now(),r=s-(t.timestamp??s);N(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r,e.tasks.executed)}updateEluWorkerUsage(e,t){const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;N(e.elu.active,s,t.taskPerformance?.elu?.active??0,e.tasks.executed),N(e.elu.idle,s,t.taskPerformance?.elu?.idle??0,e.tasks.executed),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().useDynamicWorker)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(d.error,t),!0!==this.opts.restartWorkerOnError||this.starting||(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),!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=>{const t=this.getWorkerNodeKeyByWorkerId(e.workerId),s=this.workerNodes[t].usage;(T(x.HARD,e.kill)||T(x.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);return this.sendToWorker(e,{checkActive:!0,workerId:t.id}),t.dynamic=!0,this.workerChoiceStrategyContext.getStrategyPolicy().useDynamicWorker&&(t.ready=!0),this.checkAndEmitDynamicWorkerCreationEvents(),e}afterWorkerNodeSetup(e){this.registerWorkerMessageListener(e,this.workerListener()),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e)}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(e).id})}redistributeQueuedTasks(e){for(;this.tasksQueueSize(e)>0;){let t=e,s=1/0,r=!1;for(const[i,o]of this.workerNodes.entries()){const n=this.getWorkerInfo(i);if(i!==e&&n.ready&&0===o.usage.tasks.queued){this.workerNodes[i].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&(r=!0),t=i;break}i!==e&&n.ready&&o.usage.tasks.queued<s&&(s=o.usage.tasks.queued,t=i)}r?this.executeTask(t,this.dequeueTask(e)):this.enqueueTask(t,this.dequeueTask(e))}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctions?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctions&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctions=e.taskFunctions)}}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.taskFunctions=e.taskFunctions,null!=this.emitter&&this.ready&&this.emitter.emit(d.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,taskError: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.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)),this.workerChoiceStrategyContext.update(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 Q(e,this.worker,this.maxSize);this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker node added not found");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 U extends A{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){s.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return s.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.on("exit",(()=>{e()}))}));t.on("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e,t.id),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send(t)}sendStartupMessageToWorker(e){this.sendToWorker(e,{ready:!1,workerId:this.workerNodes[e].worker.id})}registerWorkerMessageListener(e,t){this.workerNodes[e].worker.on("message",t)}createWorker(){return s.fork(this.opts.env)}get type(){return k.fixed}get worker(){return q.cluster}get busy(){return this.internalBusy()}}class D extends A{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return t.isMainThread}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.on("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e,s.threadId),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage(t,s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e].worker,s=this.workerNodes[e].messageChannel.port2;t.postMessage({ready:!1,workerId:t.threadId,port:s},[s])}registerWorkerMessageListener(e,t){this.workerNodes[e].messageChannel.port1.on("message",t)}createWorker(){return new t.Worker(this.filePath,{env:t.SHARE_ENV,...this.opts.workerOptions})}get type(){return k.fixed}get worker(){return q.thread}get busy(){return this.internalBusy()}}const B=6e4,L={killBehavior:x.SOFT,maxInactiveTime:B,killHandler:g};class _ extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=L){super(e),this.isMain=t,this.mainWorker=s,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(r),this.isMain||this.getMainWorker()?.on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){this.opts={...L,...e},delete this.opts.async}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(!f(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)){if("string"!=typeof s)throw new TypeError("A taskFunctions parameter object key is not a string");if("string"==typeof s&&0===s.trim().length)throw new TypeError("A taskFunctions parameter object key an empty string");if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");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){return this.checkTaskFunctionName(e),this.taskFunctions.has(e)}addTaskFunction(e,t){if(this.checkTaskFunctionName(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");try{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.sendTaskFunctionsListToMainWorker(),!0}catch{return!1}}removeTaskFunction(e){if(this.checkTaskFunctionName(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.sendTaskFunctionsListToMainWorker(),t}listTaskFunctions(){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){if(this.checkTaskFunctionName(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");try{return this.taskFunctions.set(l,this.taskFunctions.get(e)),!0}catch{return!1}}checkTaskFunctionName(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")}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleKillMessage(e){if(this.stopCheckActive(),W(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>(this.sendToMainWorker({kill:"success",workerId:this.id}),null))).catch((()=>{this.sendToMainWorker({kill:"failure",workerId:this.id})})).finally((()=>{this.emitDestroy()})).catch(g);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success",workerId:this.id})}catch{this.sendToMainWorker({kill:"failure",workerId:this.id})}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=i.performance.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??B)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){i.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??B)&&this.sendToMainWorker({kill:this.opts.killBehavior,workerId:this.id})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}sendTaskFunctionsListToMainWorker(){this.sendToMainWorker({taskFunctions:this.listTaskFunctions(),workerId:this.id})}handleError(e){return e instanceof Error?e.message:e}run(e){const t=this.getTaskFunction(e.name);W(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}runSync(e,t){const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,workerId:this.id,taskId:r})}catch(e){const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??l,message:t,data:i},workerId:this.id,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,workerId:this.id,taskId:r}),null))).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??l,message:t,data:i},workerId:this.id,taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(g)}getTaskFunction(e){e=e??l;const t=this.taskFunctions.get(e);if(null==t)throw new Error(`Task function '${e}' not found`);return t}beginTaskPerformance(e){return this.checkStatistics(),{name:e??l,timestamp:i.performance.now(),...this.statistics.elu&&{elu:i.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:i.performance.now()-e.timestamp},...this.statistics.elu&&{elu:i.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=i.performance.now())}}exports.ClusterWorker=class extends _{constructor(e,t={}){super("worker-cluster-pool:poolifier",s.isPrimary,s.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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}},exports.DynamicClusterPool=class extends U{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends D{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=U,exports.FixedThreadPool=D,exports.KillBehaviors=x,exports.Measurements=E,exports.PoolEvents=d,exports.PoolTypes=k,exports.ThreadWorker=class extends _{port;constructor(e,s={}){super("worker-thread-pool:poolifier",t.isMainThread,t.parentPort,e,s)}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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}handleKillMessage(e){super.handleKillMessage(e),this.port?.unref(),this.port?.close()}get id(){return t.threadId}sendToMainWorker(e){this.port.postMessage(e)}handleError(e){return e}},exports.WorkerChoiceStrategies=S,exports.WorkerTypes=q,exports.availableParallelism=()=>{let e=1;try{e=u.availableParallelism()}catch{const t=u.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
1
+ "use strict";var e=require("node:events"),t=require("node:worker_threads"),s=require("node:cluster"),r=require("node:crypto"),i=require("node:perf_hooks"),o=require("node:fs"),n=require("node:os"),a=require("node:async_hooks");function h(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}})),t.default=e,Object.freeze(t)}var u=h(n);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="default",g=Object.freeze((()=>{})),m={choiceRetries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},p={aggregate:!1,average:!1,median:!1},w=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},y=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},f=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),T=(e,t)=>t===e,W=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,N=(e,t,s,r)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=Math.min(s,e.minimum??1/0),e.maximum=Math.max(s,e.maximum??-1/0),t.average&&0!==r&&(e.average=e.aggregate/r),t.median&&null!=s&&(e.history.push(s),e.median=w(e.history)))},x=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),S=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"}),E=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class b{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)}getWorkerTaskRunTime(e){return this.taskStatisticsRequirements.runTime.median?this.pool.workerNodes[e].usage.runTime?.median??0:this.pool.workerNodes[e].usage.runTime?.average??0}getWorkerTaskWaitTime(e){return this.taskStatisticsRequirements.waitTime.median?this.pool.workerNodes[e].usage.waitTime?.median??0:this.pool.workerNodes[e].usage.waitTime?.average??0}getWorkerTaskElu(e){return this.taskStatisticsRequirements.elu.median?this.pool.workerNodes[e].usage.elu.active?.median??0:this.pool.workerNodes[e].usage.elu.active?.average??0}checkNextWorkerNodeEligibility(e){this.isWorkerNodeEligible(this.nextWorkerNodeKey)||(this.nextWorkerNodeKey=void 0,this.previousWorkerNodeKey=e??this.previousWorkerNodeKey)}computeDefaultWorkerWeight(){let e=0;for(const t of n.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/n.cpus().length)}}class I extends b{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:{aggregate:!0,average:!0,median:!1}};workersVirtualTaskEndTimestamp=[];constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.workersVirtualTaskEndTimestamp=[],!0}update(e){return this.computeWorkerVirtualTaskEndTimestamp(e),!0}choose(){return this.nextWorkerNodeKey=this.fairShareNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}fairShareNextWorkerNodeKey(){let e,t=1/0;for(const[s]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[s]&&this.computeWorkerVirtualTaskEndTimestamp(s);const r=this.workersVirtualTaskEndTimestamp[s];this.isWorkerNodeEligible(s)&&r<t&&(t=r,e=s)}return e}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===E.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class C extends b{roundId=0;roundWeights;defaultWorkerWeight;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,!0}update(){return!0}choose(){let e,t=this.roundId;for(let s=this.roundId;s<this.roundWeights.length;s++){t=s;for(let t=this.nextWorkerNodeKey??this.previousWorkerNodeKey;t<this.pool.workerNodes.length;t++){const r=this.opts.weights?.[t]??this.defaultWorkerWeight;if(this.isWorkerNodeEligible(t)&&r>=this.roundWeights[s]){e=t;break}}}this.roundId=t,null==e&&(this.previousWorkerNodeKey=this.nextWorkerNodeKey??this.previousWorkerNodeKey),this.nextWorkerNodeKey=e;const s=this.nextWorkerNodeKey;return this.nextWorkerNodeKey===this.pool.workerNodes.length-1?(this.nextWorkerNodeKey=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeKey=(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,s}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+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 v extends b{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.nextWorkerNodeKey=this.leastBusyNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastBusyNextWorkerNodeKey(){let e,t=1/0;for(const[s,r]of this.pool.workerNodes.entries()){const i=(r.usage.runTime?.aggregate??0)+(r.usage.waitTime?.aggregate??0);if(this.isWorkerNodeEligible(s)&&0===i){e=s;break}this.isWorkerNodeEligible(s)&&i<t&&(t=i,e=s)}return e}}class R extends b{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){let e,t=1/0;for(const[s,r]of this.pool.workerNodes.entries()){const i=r.usage.tasks,o=i.executed+i.executing+i.queued;if(this.isWorkerNodeEligible(s)&&0===o){e=s;break}this.isWorkerNodeEligible(s)&&o<t&&(t=o,e=s)}return e}}class O extends b{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.nextWorkerNodeKey=this.leastEluNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastEluNextWorkerNodeKey(){let e,t=1/0;for(const[s,r]of this.pool.workerNodes.entries()){const i=r.usage,o=i.elu?.active?.aggregate??0;if(this.isWorkerNodeEligible(s)&&0===o){e=s;break}this.isWorkerNodeEligible(s)&&o<t&&(t=o,e=s)}return e}}class F extends b{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.roundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeEligibility(e),e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=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 z extends b{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:p,elu:p};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.weightedRoundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeEligibility(e),e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.workerVirtualTaskRunTime;return e<(this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=e+this.getWorkerTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class M{workerChoiceStrategy;opts;workerChoiceStrategies;choiceRetriesCount=0;constructor(e,t=S.ROUND_ROBIN,s=m){this.workerChoiceStrategy=t,this.opts=s,this.opts={...m,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[S.ROUND_ROBIN,new(F.bind(this))(e,s)],[S.LEAST_USED,new(R.bind(this))(e,s)],[S.LEAST_BUSY,new(v.bind(this))(e,s)],[S.LEAST_ELU,new(O.bind(this))(e,s)],[S.FAIR_SHARE,new(I.bind(this))(e,s)],[S.WEIGHTED_ROUND_ROBIN,new(z.bind(this))(e,s)],[S.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(C.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.choiceRetriesCount<this.opts.choiceRetries)return this.choiceRetriesCount++,this.execute();if(null==e)throw new Error(`Worker node key chosen is null or undefined after ${this.choiceRetriesCount} retries`);return this.choiceRetriesCount=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 K 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 K(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 P{items;offset;size;maxSize;constructor(){this.clear()}enqueue(e){return this.items.push(e),++this.size,this.size>this.maxSize&&(this.maxSize=this.size),this.size}dequeue(){if(this.size<=0)return;const e=this.items[this.offset];return 2*++this.offset>=this.items.length&&(this.items=this.items.slice(this.offset),this.offset=0),--this.size,e}peek(){if(!(this.size<=0))return this.items[this.offset]}clear(){this.items=[],this.offset=0,this.size=0,this.maxSize=0}[Symbol.iterator](){const e=this.items;let t=this.offset;return{next:()=>{if(t>=e.length)return{value:void 0,done:!0};const s=e[t];return++t,{value:s,done:!1}}}}}const q=Object.freeze({thread:"thread",cluster:"cluster"});class Q{worker;info;messageChannel;usage;taskFunctionsUsage;tasksQueue;tasksQueueBackPressureSize;constructor(e,s,r){if(null==e)throw new TypeError("Cannot construct a worker node without a worker");if(null==s)throw new TypeError("Cannot construct a worker node without a worker type");if(null==r)throw new TypeError("Cannot construct a worker node without a pool maximum size");if(!Number.isSafeInteger(r))throw new TypeError("Cannot construct a worker node with a pool maximum size that is not an integer");this.worker=e,this.info=this.initWorkerInfo(e,s),s===q.thread&&(this.messageChannel=new t.MessageChannel),this.usage=this.initWorkerUsage(),this.taskFunctionsUsage=new Map,this.tasksQueue=new P,this.tasksQueueBackPressureSize=Math.pow(r,2)}tasksQueueSize(){return this.tasksQueue.size}tasksQueueMaxSize(){return this.tasksQueue.maxSize}enqueueTask(e){return this.tasksQueue.enqueue(e)}dequeueTask(){return this.tasksQueue.dequeue()}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.taskFunctions))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.taskFunctions)&&this.info.taskFunctions.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.taskFunctions[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}initWorkerInfo(e,t){return{id:this.getWorkerId(e,t),type:t,dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueueSize(),t=()=>this.tasksQueueMaxSize();return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},failed:0},runTime:{history:new K},waitTime:{history:new K},elu:{idle:{history:new K},active:{history:new K}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===l&&e===this.info.taskFunctions[1]||s.name!==l&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},failed:0},runTime:{history:new K},waitTime:{history:new K},elu:{idle:{history:new K},active:{history:new K}}}}getWorkerId(e,t){return t===q.thread?e.threadId:t===q.cluster?e.id:void 0}}class A{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;starting;startTimestamp;constructor(e,t,s){if(this.numberOfWorkers=e,this.filePath=t,this.opts=s,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),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 M(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.starting=!0,this.startPool(),this.starting=!1,this.startTimestamp=i.performance.now()}checkFilePath(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(!o.existsSync(e))throw new Error(`Cannot find the worker file '${e}'`)}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")}checkDynamicPoolSize(e,t){if(this.type===k.dynamic){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")}}checkPoolOptions(e){if(!f(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??S.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions={...m,...e.workerChoiceStrategyOptions},this.checkValidWorkerChoiceStrategyOptions(this.opts.workerChoiceStrategyOptions),this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(this.checkValidTasksQueueOptions(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategy(e){if(!Object.values(S).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!f(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.choiceRetries&&!Number.isSafeInteger(e.choiceRetries))throw new TypeError("Invalid worker choice strategy options: choice retries must be an integer");if(null!=e.choiceRetries&&e.choiceRetries<=0)throw new RangeError(`Invalid worker choice strategy options: choice retries '${e.choiceRetries}' must be greater 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(E).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(e){if(null!=e&&!f(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 tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new RangeError(`Invalid worker tasks concurrency: ${e.concurrency} is a negative integer or zero`)}startPool(){for(;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode()}get info(){return{version:"2.6.31",type:this.type,worker:this.worker,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:y(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()},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:y(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:y(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:y(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:y(w(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:y(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:y(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:y(this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:y(w(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(i.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){this.checkValidWorkerChoiceStrategy(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.flushTasksQueues(),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(this.checkValidTasksQueueOptions(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e)):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{concurrency:e?.concurrency??1}}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))}listTaskFunctions(){for(const e of this.workerNodes)if(Array.isArray(e.info.taskFunctions)&&e.info.taskFunctions.length>0)return e.info.taskFunctions;return[]}async execute(e,t,s){return await new Promise(((o,n)=>{null!=t&&"string"!=typeof t&&n(new TypeError("name argument must be a string")),null!=t&&"string"==typeof t&&0===t.trim().length&&n(new TypeError("name argument must not be an empty string")),null==s||Array.isArray(s)||n(new TypeError("transferList argument must be an array"));const a=i.performance.now(),h=this.chooseWorkerNode(),u=this.getWorkerInfo(h);null!=t&&Array.isArray(u.taskFunctions)&&!u.taskFunctions.includes(t)&&n(new Error(`Task function '${t}' is not registered in the pool`));const k={name:t??l,data:e??{},transferList:s,timestamp:a,workerId:u.id,taskId:r.randomUUID()};this.promiseResponseMap.set(k.taskId,{resolve:o,reject:n,workerNodeKey:h}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.workerNodes[h].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency?this.executeTask(h,k):this.enqueueTask(h,k)}))}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(d.destroy,this.info)}async sendKillMessageToWorker(e,t){await new Promise(((s,r)=>{this.registerWorkerMessageListener(e,(e=>{"success"===e.kill?s():"failure"===e.kill&&r(new Error(`Worker ${t} kill message handling failed`))})),this.sendToWorker(e,{kill:!0,workerId:t})}))}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??l);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.taskFunctions)&&t.taskFunctions.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;if(null!=s.executing&&s.executing>0)--s.executing;else if(null!=s.executing&&s.executing<0)throw new Error("Worker usage statistic for tasks executing cannot be negative");null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){N(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0,e.tasks.executed)}updateWaitTimeWorkerUsage(e,t){const s=i.performance.now(),r=s-(t.timestamp??s);N(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r,e.tasks.executed)}updateEluWorkerUsage(e,t){const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;N(e.elu.active,s,t.taskPerformance?.elu?.active??0,e.tasks.executed),N(e.elu.idle,s,t.taskPerformance?.elu?.idle??0,e.tasks.executed),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(d.error,t),!0!==this.opts.restartWorkerOnError||this.starting||(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),!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=>{const t=this.getWorkerNodeKeyByWorkerId(e.workerId),s=this.workerNodes[t].usage;(T(x.HARD,e.kill)||T(x.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);return this.sendToWorker(e,{checkActive:!0,workerId:t.id}),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)}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(e).id})}redistributeQueuedTasks(e){for(;this.tasksQueueSize(e)>0;){let t=e,s=1/0,r=!1;for(const[i,o]of this.workerNodes.entries()){const n=this.getWorkerInfo(i);if(i!==e&&n.ready&&0===o.usage.tasks.queued){this.workerNodes[i].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&(r=!0),t=i;break}i!==e&&n.ready&&o.usage.tasks.queued<s&&(s=o.usage.tasks.queued,t=i)}r?this.executeTask(t,this.dequeueTask(e)):this.enqueueTask(t,this.dequeueTask(e))}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctions?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctions&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctions=e.taskFunctions)}}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.taskFunctions=e.taskFunctions,null!=this.emitter&&this.ready&&this.emitter.emit(d.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,taskError: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.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)),this.workerChoiceStrategyContext.update(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 Q(e,this.worker,this.maxSize);this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker node added not found");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 U extends A{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){s.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return s.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.on("exit",(()=>{e()}))}));t.on("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e,t.id),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send(t)}sendStartupMessageToWorker(e){this.sendToWorker(e,{ready:!1,workerId:this.workerNodes[e].worker.id})}registerWorkerMessageListener(e,t){this.workerNodes[e].worker.on("message",t)}createWorker(){return s.fork(this.opts.env)}get type(){return k.fixed}get worker(){return q.cluster}get busy(){return this.internalBusy()}}class B extends A{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return t.isMainThread}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.on("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e,s.threadId),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage(t,s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e].worker,s=this.workerNodes[e].messageChannel.port2;t.postMessage({ready:!1,workerId:t.threadId,port:s},[s])}registerWorkerMessageListener(e,t){this.workerNodes[e].messageChannel.port1.on("message",t)}createWorker(){return new t.Worker(this.filePath,{env:t.SHARE_ENV,...this.opts.workerOptions})}get type(){return k.fixed}get worker(){return q.thread}get busy(){return this.internalBusy()}}const D=6e4,L={killBehavior:x.SOFT,maxInactiveTime:D,killHandler:g};class _ extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=L){super(e),this.isMain=t,this.mainWorker=s,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(r),this.isMain||this.getMainWorker()?.on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){this.opts={...L,...e},delete this.opts.async}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(!f(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)){if("string"!=typeof s)throw new TypeError("A taskFunctions parameter object key is not a string");if("string"==typeof s&&0===s.trim().length)throw new TypeError("A taskFunctions parameter object key an empty string");if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");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){return this.checkTaskFunctionName(e),this.taskFunctions.has(e)}addTaskFunction(e,t){if(this.checkTaskFunctionName(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");try{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.sendTaskFunctionsListToMainWorker(),!0}catch{return!1}}removeTaskFunction(e){if(this.checkTaskFunctionName(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.sendTaskFunctionsListToMainWorker(),t}listTaskFunctions(){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){if(this.checkTaskFunctionName(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");try{return this.taskFunctions.set(l,this.taskFunctions.get(e)),!0}catch{return!1}}checkTaskFunctionName(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")}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleKillMessage(e){if(this.stopCheckActive(),W(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>(this.sendToMainWorker({kill:"success",workerId:this.id}),null))).catch((()=>{this.sendToMainWorker({kill:"failure",workerId:this.id})})).finally((()=>{this.emitDestroy()})).catch(g);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success",workerId:this.id})}catch{this.sendToMainWorker({kill:"failure",workerId:this.id})}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=i.performance.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??D)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){i.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??D)&&this.sendToMainWorker({kill:this.opts.killBehavior,workerId:this.id})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}sendTaskFunctionsListToMainWorker(){this.sendToMainWorker({taskFunctions:this.listTaskFunctions(),workerId:this.id})}handleError(e){return e instanceof Error?e.message:e}run(e){const t=this.getTaskFunction(e.name);W(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}runSync(e,t){const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,workerId:this.id,taskId:r})}catch(e){const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??l,message:t,data:i},workerId:this.id,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,workerId:this.id,taskId:r}),null))).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??l,message:t,data:i},workerId:this.id,taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(g)}getTaskFunction(e){e=e??l;const t=this.taskFunctions.get(e);if(null==t)throw new Error(`Task function '${e}' not found`);return t}beginTaskPerformance(e){return this.checkStatistics(),{name:e??l,timestamp:i.performance.now(),...this.statistics.elu&&{elu:i.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:i.performance.now()-e.timestamp},...this.statistics.elu&&{elu:i.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=i.performance.now())}}exports.ClusterWorker=class extends _{constructor(e,t={}){super("worker-cluster-pool:poolifier",s.isPrimary,s.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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}},exports.DynamicClusterPool=class extends U{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends B{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return k.dynamic}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=U,exports.FixedThreadPool=B,exports.KillBehaviors=x,exports.Measurements=E,exports.PoolEvents=d,exports.PoolTypes=k,exports.ThreadWorker=class extends _{port;constructor(e,s={}){super("worker-thread-pool:poolifier",t.isMainThread,t.parentPort,e,s)}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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}handleKillMessage(e){super.handleKillMessage(e),this.port?.unref(),this.port?.close()}get id(){return t.threadId}sendToMainWorker(e){this.port.postMessage(e)}handleError(e){return e}},exports.WorkerChoiceStrategies=S,exports.WorkerTypes=q,exports.availableParallelism=()=>{let e=1;try{e=u.availableParallelism()}catch{const t=u.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e};
package/lib/index.mjs CHANGED
@@ -1 +1 @@
1
- import{EventEmitter as e}from"node:events";import{MessageChannel as t,isMainThread as s,Worker as r,SHARE_ENV as i,parentPort as o,threadId as n}from"node:worker_threads";import a from"node:cluster";import{randomUUID as h}from"node:crypto";import{performance as u}from"node:perf_hooks";import{existsSync as k}from"node:fs";import*as c from"node:os";import{cpus as d}from"node:os";import{AsyncResource as l}from"node:async_hooks";const g=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class m extends e{}const w=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),p="default",y=Object.freeze((()=>{})),f={choiceRetries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},T={aggregate:!1,average:!1,median:!1},W=()=>{let e=1;try{e=c.availableParallelism()}catch{const t=c.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e},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},x=(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),E=(e,t)=>t===e,b=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,I=(e,t,s,r)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=Math.min(s,e.minimum??1/0),e.maximum=Math.max(s,e.maximum??-1/0),t.average&&0!==r&&(e.average=e.aggregate/r),t.median&&null!=s&&(e.history.push(s),e.median=N(e.history)))},C=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),R=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"}),v=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class z{pool;opts;nextWorkerNodeKey=0;strategyPolicy={useDynamicWorker:!1};taskStatisticsRequirements={runTime:T,waitTime:T,elu:T};constructor(e,t=f){this.pool=e,this.opts=t,this.opts={...f,...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)}setOptions(e){this.opts={...f,...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)}getWorkerTaskRunTime(e){return this.taskStatisticsRequirements.runTime.median?this.pool.workerNodes[e].usage.runTime?.median??0:this.pool.workerNodes[e].usage.runTime?.average??0}getWorkerTaskWaitTime(e){return this.taskStatisticsRequirements.waitTime.median?this.pool.workerNodes[e].usage.waitTime?.median??0:this.pool.workerNodes[e].usage.waitTime?.average??0}getWorkerTaskElu(e){return this.taskStatisticsRequirements.elu.median?this.pool.workerNodes[e].usage.elu.active?.median??0:this.pool.workerNodes[e].usage.elu.active?.average??0}computeDefaultWorkerWeight(){let e=0;for(const t of d()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/d().length)}}class F extends z{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:T,elu:{aggregate:!0,average:!0,median:!1}};workersVirtualTaskEndTimestamp=[];constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.workersVirtualTaskEndTimestamp=[],!0}update(e){return this.computeWorkerVirtualTaskEndTimestamp(e),!0}choose(){return this.fairShareNextWorkerNodeKey()}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}fairShareNextWorkerNodeKey(){let e=1/0;for(const[t]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[t]&&this.computeWorkerVirtualTaskEndTimestamp(t);const s=this.workersVirtualTaskEndTimestamp[t];this.isWorkerNodeEligible(t)&&s<e&&(e=s,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===v.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class O extends z{strategyPolicy={useDynamicWorker:!0};roundId=0;roundWeights;defaultWorkerWeight;constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.nextWorkerNodeKey=0,this.roundId=0,!0}update(){return!0}choose(){let e,t;for(let s=this.roundId;s<this.roundWeights.length;s++)for(let r=this.nextWorkerNodeKey;r<this.pool.workerNodes.length;r++){const i=this.opts.weights?.[r]??this.defaultWorkerWeight;if(this.isWorkerNodeEligible(r)&&i>=this.roundWeights[s]){e=s,t=r;break}}this.roundId=e??0,this.nextWorkerNodeKey=t??0;const s=this.nextWorkerNodeKey;return this.nextWorkerNodeKey===this.pool.workerNodes.length-1?(this.nextWorkerNodeKey=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeKey=this.nextWorkerNodeKey+1,s}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+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 M extends z{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:T};constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.leastBusyNextWorkerNodeKey()}remove(){return!0}leastBusyNextWorkerNodeKey(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=(s.usage.runTime?.aggregate??0)+(s.usage.waitTime?.aggregate??0);if(this.isWorkerNodeEligible(t)&&0===r){this.nextWorkerNodeKey=t;break}this.isWorkerNodeEligible(t)&&r<e&&(e=r,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}}class K extends z{constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.leastUsedNextWorkerNodeKey()}remove(){return!0}leastUsedNextWorkerNodeKey(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage.tasks,i=r.executed+r.executing+r.queued;if(this.isWorkerNodeEligible(t)&&0===i){this.nextWorkerNodeKey=t;break}this.isWorkerNodeEligible(t)&&i<e&&(e=i,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}}class Q extends z{taskStatisticsRequirements={runTime:T,waitTime:T,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.leastEluNextWorkerNodeKey()}remove(){return!0}leastEluNextWorkerNodeKey(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage,i=r.elu?.active?.aggregate??0;if(this.isWorkerNodeEligible(t)&&0===i){this.nextWorkerNodeKey=t;break}this.isWorkerNodeEligible(t)&&i<e&&(e=i,this.nextWorkerNodeKey=t)}return this.nextWorkerNodeKey}}class A extends z{strategyPolicy={useDynamicWorker:!0};constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.nextWorkerNodeKey=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;do{this.roundRobinNextWorkerNodeKey()}while(!this.isWorkerNodeEligible(this.nextWorkerNodeKey));return e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1)),!0}roundRobinNextWorkerNodeKey(){return this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:this.nextWorkerNodeKey+1,this.nextWorkerNodeKey}}class q extends z{strategyPolicy={useDynamicWorker:!0};taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:T,elu:T};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.nextWorkerNodeKey=0,this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;do{this.weightedRoundRobinNextWorkerNodeKey()}while(!this.isWorkerNodeEligible(this.nextWorkerNodeKey));return e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.workerVirtualTaskRunTime;return e<(this.opts.weights?.[this.nextWorkerNodeKey]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=e+this.getWorkerTaskRunTime(this.nextWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:this.nextWorkerNodeKey+1,this.workerVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class P{workerChoiceStrategy;opts;workerChoiceStrategies;choiceRetriesCount=0;constructor(e,t=R.ROUND_ROBIN,s=f){this.workerChoiceStrategy=t,this.opts=s,this.opts={...f,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[R.ROUND_ROBIN,new(A.bind(this))(e,s)],[R.LEAST_USED,new(K.bind(this))(e,s)],[R.LEAST_BUSY,new(M.bind(this))(e,s)],[R.LEAST_ELU,new(Q.bind(this))(e,s)],[R.FAIR_SHARE,new(F.bind(this))(e,s)],[R.WEIGHTED_ROUND_ROBIN,new(q.bind(this))(e,s)],[R.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(O.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.choiceRetriesCount<this.opts.choiceRetries)return this.choiceRetriesCount++,this.execute();if(null==e)throw new TypeError(`Worker node key chosen is null or undefined after ${this.choiceRetriesCount} retries`);return this.choiceRetriesCount=0,e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...f,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class U 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 U(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 D{items;offset;size;maxSize;constructor(){this.clear()}enqueue(e){return this.items.push(e),++this.size,this.size>this.maxSize&&(this.maxSize=this.size),this.size}dequeue(){if(this.size<=0)return;const e=this.items[this.offset];return 2*++this.offset>=this.items.length&&(this.items=this.items.slice(this.offset),this.offset=0),--this.size,e}peek(){if(!(this.size<=0))return this.items[this.offset]}clear(){this.items=[],this.offset=0,this.size=0,this.maxSize=0}[Symbol.iterator](){const e=this.items;let t=this.offset;return{next:()=>{if(t>=e.length)return{value:void 0,done:!0};const s=e[t];return++t,{value:s,done:!1}}}}}const B=Object.freeze({thread:"thread",cluster:"cluster"});class L{worker;info;messageChannel;usage;taskFunctionsUsage;tasksQueue;tasksQueueBackPressureSize;constructor(e,s,r){if(null==e)throw new Error("Cannot construct a worker node without a worker");if(null==s)throw new Error("Cannot construct a worker node without a worker type");if(null==r)throw new Error("Cannot construct a worker node without a pool maximum size");if(isNaN(r))throw new Error("Cannot construct a worker node with a NaN pool maximum size");this.worker=e,this.info=this.initWorkerInfo(e,s),s===B.thread&&(this.messageChannel=new t),this.usage=this.initWorkerUsage(),this.taskFunctionsUsage=new Map,this.tasksQueue=new D,this.tasksQueueBackPressureSize=Math.pow(r,2)}tasksQueueSize(){return this.tasksQueue.size}tasksQueueMaxSize(){return this.tasksQueue.maxSize}enqueueTask(e){return this.tasksQueue.enqueue(e)}dequeueTask(){return this.tasksQueue.dequeue()}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.taskFunctions))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.taskFunctions)&&this.info.taskFunctions.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===p&&(e=this.info.taskFunctions[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}initWorkerInfo(e,t){return{id:this.getWorkerId(e,t),type:t,dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueueSize(),t=()=>this.tasksQueueMaxSize();return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},failed:0},runTime:{history:new U},waitTime:{history:new U},elu:{idle:{history:new U},active:{history:new U}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)s.name===e&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},failed:0},runTime:{history:new U},waitTime:{history:new U},elu:{idle:{history:new U},active:{history:new U}}}}getWorkerId(e,t){return t===B.thread?e.threadId:t===B.cluster?e.id:void 0}}class _{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;starting;startTimestamp;constructor(e,t,s){if(this.numberOfWorkers=e,this.filePath=t,this.opts=s,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),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 m),this.workerChoiceStrategyContext=new P(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.starting=!0,this.startPool(),this.starting=!1,this.startTimestamp=u.now()}checkFilePath(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(!k(e))throw new Error(`Cannot find the worker file '${e}'`)}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===g.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkDynamicPoolSize(e,t){if(this.type===g.dynamic){if(null==t)throw new Error("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")}}checkPoolOptions(e){if(!S(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??R.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions={...f,...e.workerChoiceStrategyOptions},this.checkValidWorkerChoiceStrategyOptions(this.opts.workerChoiceStrategyOptions),this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(this.checkValidTasksQueueOptions(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategy(e){if(!Object.values(R).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!S(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.choiceRetries&&!Number.isSafeInteger(e.choiceRetries))throw new TypeError("Invalid worker choice strategy options: choice retries must be an integer");if(null!=e.choiceRetries&&e.choiceRetries<=0)throw new RangeError(`Invalid worker choice strategy options: choice retries '${e.choiceRetries}' must be greater 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(v).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(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 tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new Error(`Invalid worker tasks concurrency: ${e.concurrency} is a negative integer or zero`)}startPool(){for(;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode()}get info(){return{version:"2.6.30",type:this.type,worker:this.worker,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:x(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()},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:x(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:x(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:x(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:x(N(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:x(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:x(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:x(this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:x(N(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(u.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){this.checkValidWorkerChoiceStrategy(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={...f,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||this.flushTasksQueues(),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(this.checkValidTasksQueueOptions(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e)):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{concurrency:e?.concurrency??1}}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))}listTaskFunctions(){for(const e of this.workerNodes)if(Array.isArray(e.info.taskFunctions)&&e.info.taskFunctions.length>0)return e.info.taskFunctions;return[]}async execute(e,t,s){return await new Promise(((r,i)=>{null!=t&&"string"!=typeof t&&i(new TypeError("name argument must be a string")),null!=t&&"string"==typeof t&&0===t.trim().length&&i(new TypeError("name argument must not be an empty string")),null==s||Array.isArray(s)||i(new TypeError("transferList argument must be an array"));const o=u.now(),n=this.chooseWorkerNode(),a=this.getWorkerInfo(n);null!=t&&Array.isArray(a.taskFunctions)&&!a.taskFunctions.includes(t)&&i(new Error(`Task function '${t}' is not registered in the pool`));const k={name:t??p,data:e??{},transferList:s,timestamp:o,workerId:a.id,taskId:h()};this.promiseResponseMap.set(k.taskId,{resolve:r,reject:i,workerNodeKey:n}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.workerNodes[n].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency?this.executeTask(n,k):this.enqueueTask(n,k)}))}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(w.destroy,this.info)}async sendKillMessageToWorker(e,t){await new Promise(((s,r)=>{this.registerWorkerMessageListener(e,(e=>{"success"===e.kill?s():"failure"===e.kill&&r(new Error(`Worker ${t} kill message handling failed`))})),this.sendToWorker(e,{kill:!0,workerId:t})}))}setupHook(){}beforeTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;if(++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t),this.shallUpdateTaskFunctionWorkerUsage(e)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.name);++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}}afterTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;if(this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t),this.shallUpdateTaskFunctionWorkerUsage(e)){const s=this.workerNodes[e].getTaskFunctionWorkerUsage(t.taskPerformance?.name??p);this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}}shallUpdateTaskFunctionWorkerUsage(e){const t=this.getWorkerInfo(e);return Array.isArray(t.taskFunctions)&&t.taskFunctions.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;if(null!=s.executing&&s.executing>0)--s.executing;else if(null!=s.executing&&s.executing<0)throw new Error("Worker usage statistic for tasks executing cannot be negative");null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){I(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0,e.tasks.executed)}updateWaitTimeWorkerUsage(e,t){const s=u.now(),r=s-(t.timestamp??s);I(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r,e.tasks.executed)}updateEluWorkerUsage(e,t){const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;I(e.elu.active,s,t.taskPerformance?.elu?.active??0,e.tasks.executed),I(e.elu.idle,s,t.taskPerformance?.elu?.idle??0,e.tasks.executed),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().useDynamicWorker)return e}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===g.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorker();e.on("online",this.opts.onlineHandler??y),e.on("message",this.opts.messageHandler??y),e.on("error",this.opts.errorHandler??y),e.on("error",(t=>{const s=this.getWorkerNodeKeyByWorker(e),r=this.getWorkerInfo(s);r.ready=!1,this.workerNodes[s].closeChannel(),this.emitter?.emit(w.error,t),!0!==this.opts.restartWorkerOnError||this.starting||(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(s)})),e.on("exit",this.opts.exitHandler??y),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=>{const t=this.getWorkerNodeKeyByWorkerId(e.workerId),s=this.workerNodes[t].usage;(E(C.HARD,e.kill)||E(C.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(w.error,e)}))}));const t=this.getWorkerInfo(e);return this.sendToWorker(e,{checkActive:!0,workerId:t.id}),t.dynamic=!0,this.workerChoiceStrategyContext.getStrategyPolicy().useDynamicWorker&&(t.ready=!0),this.checkAndEmitDynamicWorkerCreationEvents(),e}afterWorkerNodeSetup(e){this.registerWorkerMessageListener(e,this.workerListener()),this.sendStartupMessageToWorker(e),this.sendStatisticsMessageToWorker(e)}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(e).id})}redistributeQueuedTasks(e){for(;this.tasksQueueSize(e)>0;){let t=e,s=1/0,r=!1;for(const[i,o]of this.workerNodes.entries()){const n=this.getWorkerInfo(i);if(i!==e&&n.ready&&0===o.usage.tasks.queued){this.workerNodes[i].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&(r=!0),t=i;break}i!==e&&n.ready&&o.usage.tasks.queued<s&&(s=o.usage.tasks.queued,t=i)}r?this.executeTask(t,this.dequeueTask(e)):this.enqueueTask(t,this.dequeueTask(e))}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctions?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctions&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctions=e.taskFunctions)}}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.taskFunctions=e.taskFunctions,null!=this.emitter&&this.ready&&this.emitter.emit(w.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,taskError:s,data:r}=e,i=this.promiseResponseMap.get(t);if(null!=i){null!=s?(this.emitter?.emit(w.taskError,s),i.reject(s.message)):i.resolve(r);const o=i.workerNodeKey;this.afterTaskExecutionHook(o,e),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)),this.workerChoiceStrategyContext.update(o)}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(w.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(w.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===g.dynamic&&this.full&&this.emitter?.emit(w.full,this.info)}getWorkerInfo(e){return this.workerNodes[e].info}addWorkerNode(e){const t=new L(e,this.worker,this.maxSize);this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker node added not found");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 V extends _{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){a.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return a.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.on("exit",(()=>{e()}))}));t.on("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e,t.id),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send(t)}sendStartupMessageToWorker(e){this.sendToWorker(e,{ready:!1,workerId:this.workerNodes[e].worker.id})}registerWorkerMessageListener(e,t){this.workerNodes[e].worker.on("message",t)}createWorker(){return a.fork(this.opts.env)}get type(){return g.fixed}get worker(){return B.cluster}get busy(){return this.internalBusy()}}class j extends V{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return g.dynamic}get busy(){return this.full&&this.internalBusy()}}class H extends _{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return s}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.on("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e,s.threadId),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage(t,s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e].worker,s=this.workerNodes[e].messageChannel.port2;t.postMessage({ready:!1,workerId:t.threadId,port:s},[s])}registerWorkerMessageListener(e,t){this.workerNodes[e].messageChannel.port1.on("message",t)}createWorker(){return new r(this.filePath,{env:i,...this.opts.workerOptions})}get type(){return g.fixed}get worker(){return B.thread}get busy(){return this.internalBusy()}}class $ extends H{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return g.dynamic}get busy(){return this.full&&this.internalBusy()}}const G=6e4,Y={killBehavior:C.SOFT,maxInactiveTime:G,killHandler:y};class J extends l{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=Y){super(e),this.isMain=t,this.mainWorker=s,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(r),this.isMain||this.getMainWorker()?.on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){this.opts={...Y,...e},delete this.opts.async}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(p,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)){if("string"!=typeof s)throw new TypeError("A taskFunctions parameter object key is not a string");if("string"==typeof s&&0===s.trim().length)throw new TypeError("A taskFunctions parameter object key an empty string");if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");const e=r.bind(this);t&&(this.taskFunctions.set(p,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){return this.checkTaskFunctionName(e),this.taskFunctions.has(e)}addTaskFunction(e,t){if(this.checkTaskFunctionName(e),e===p)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");try{const s=t.bind(this);return this.taskFunctions.get(e)===this.taskFunctions.get(p)&&this.taskFunctions.set(p,s),this.taskFunctions.set(e,s),this.sendTaskFunctionsListToMainWorker(),!0}catch{return!1}}removeTaskFunction(e){if(this.checkTaskFunctionName(e),e===p)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(p))throw new Error("Cannot remove the task function used as the default task function");const t=this.taskFunctions.delete(e);return this.sendTaskFunctionsListToMainWorker(),t}listTaskFunctions(){const e=[...this.taskFunctions.keys()];let t=p;for(const[e,s]of this.taskFunctions)if(e!==p&&s===this.taskFunctions.get(p)){t=e;break}return[e[e.indexOf(p)],t,...e.filter((e=>e!==p&&e!==t))]}setDefaultTaskFunction(e){if(this.checkTaskFunctionName(e),e===p)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");try{return this.taskFunctions.set(p,this.taskFunctions.get(e)),!0}catch{return!1}}checkTaskFunctionName(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")}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleKillMessage(e){if(this.stopCheckActive(),b(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>(this.sendToMainWorker({kill:"success",workerId:this.id}),null))).catch((()=>{this.sendToMainWorker({kill:"failure",workerId:this.id})})).finally((()=>{this.emitDestroy()})).catch(y);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success",workerId:this.id})}catch{this.sendToMainWorker({kill:"failure",workerId:this.id})}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=u.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??G)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){u.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??G)&&this.sendToMainWorker({kill:this.opts.killBehavior,workerId:this.id})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}sendTaskFunctionsListToMainWorker(){this.sendToMainWorker({taskFunctions:this.listTaskFunctions(),workerId:this.id})}handleError(e){return e instanceof Error?e.message:e}run(e){const t=this.getTaskFunction(e.name);b(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}runSync(e,t){const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,workerId:this.id,taskId:r})}catch(e){const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??p,message:t,data:i},workerId:this.id,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,workerId:this.id,taskId:r}),null))).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??p,message:t,data:i},workerId:this.id,taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(y)}getTaskFunction(e){e=e??p;const t=this.taskFunctions.get(e);if(null==t)throw new Error(`Task function '${e}' not found`);return t}beginTaskPerformance(e){return this.checkStatistics(),{name:e??p,timestamp:u.now(),...this.statistics.elu&&{elu:u.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:u.now()-e.timestamp},...this.statistics.elu&&{elu:u.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=u.now())}}class X extends J{constructor(e,t={}){super("worker-cluster-pool:poolifier",a.isPrimary,a.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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}}class Z extends J{port;constructor(e,t={}){super("worker-thread-pool:poolifier",s,o,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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}handleKillMessage(e){super.handleKillMessage(e),this.port?.unref(),this.port?.close()}get id(){return n}sendToMainWorker(e){this.port.postMessage(e)}handleError(e){return e}}export{X as ClusterWorker,j as DynamicClusterPool,$ as DynamicThreadPool,V as FixedClusterPool,H as FixedThreadPool,C as KillBehaviors,v as Measurements,w as PoolEvents,g as PoolTypes,Z as ThreadWorker,R as WorkerChoiceStrategies,B as WorkerTypes,W as availableParallelism};
1
+ import{EventEmitter as e}from"node:events";import{MessageChannel as t,isMainThread as s,Worker as r,SHARE_ENV as i,parentPort as o,threadId as n}from"node:worker_threads";import a from"node:cluster";import{randomUUID as h}from"node:crypto";import{performance as u}from"node:perf_hooks";import{existsSync as k}from"node:fs";import*as c from"node:os";import{cpus as d}from"node:os";import{AsyncResource as l}from"node:async_hooks";const g=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class m extends e{}const p=Object.freeze({ready:"ready",busy:"busy",full:"full",destroy:"destroy",error:"error",taskError:"taskError",backPressure:"backPressure"}),w="default",y=Object.freeze((()=>{})),f={choiceRetries:6,runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},T={aggregate:!1,average:!1,median:!1},W=()=>{let e=1;try{e=c.availableParallelism()}catch{const t=c.cpus();Array.isArray(t)&&t.length>0&&(e=t.length)}return e},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},x=(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),E=(e,t)=>t===e,b=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,I=(e,t,s,r)=>{t.aggregate&&(e.aggregate=(e.aggregate??0)+s,e.minimum=Math.min(s,e.minimum??1/0),e.maximum=Math.max(s,e.maximum??-1/0),t.average&&0!==r&&(e.average=e.aggregate/r),t.median&&null!=s&&(e.history.push(s),e.median=N(e.history)))},C=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),v=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LEAST_USED:"LEAST_USED",LEAST_BUSY:"LEAST_BUSY",LEAST_ELU:"LEAST_ELU",FAIR_SHARE:"FAIR_SHARE",WEIGHTED_ROUND_ROBIN:"WEIGHTED_ROUND_ROBIN",INTERLEAVED_WEIGHTED_ROUND_ROBIN:"INTERLEAVED_WEIGHTED_ROUND_ROBIN"}),R=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class F{pool;opts;nextWorkerNodeKey=0;previousWorkerNodeKey=0;strategyPolicy={dynamicWorkerUsage:!1,dynamicWorkerReady:!0};taskStatisticsRequirements={runTime:T,waitTime:T,elu:T};constructor(e,t=f){this.pool=e,this.opts=t,this.opts={...f,...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={...f,...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)}getWorkerTaskRunTime(e){return this.taskStatisticsRequirements.runTime.median?this.pool.workerNodes[e].usage.runTime?.median??0:this.pool.workerNodes[e].usage.runTime?.average??0}getWorkerTaskWaitTime(e){return this.taskStatisticsRequirements.waitTime.median?this.pool.workerNodes[e].usage.waitTime?.median??0:this.pool.workerNodes[e].usage.waitTime?.average??0}getWorkerTaskElu(e){return this.taskStatisticsRequirements.elu.median?this.pool.workerNodes[e].usage.elu.active?.median??0:this.pool.workerNodes[e].usage.elu.active?.average??0}checkNextWorkerNodeEligibility(e){this.isWorkerNodeEligible(this.nextWorkerNodeKey)||(this.nextWorkerNodeKey=void 0,this.previousWorkerNodeKey=e??this.previousWorkerNodeKey)}computeDefaultWorkerWeight(){let e=0;for(const t of d()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/d().length)}}class z extends F{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:T,elu:{aggregate:!0,average:!0,median:!1}};workersVirtualTaskEndTimestamp=[];constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.workersVirtualTaskEndTimestamp=[],!0}update(e){return this.computeWorkerVirtualTaskEndTimestamp(e),!0}choose(){return this.nextWorkerNodeKey=this.fairShareNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}fairShareNextWorkerNodeKey(){let e,t=1/0;for(const[s]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[s]&&this.computeWorkerVirtualTaskEndTimestamp(s);const r=this.workersVirtualTaskEndTimestamp[s];this.isWorkerNodeEligible(s)&&r<t&&(t=r,e=s)}return e}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===R.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class O extends F{roundId=0;roundWeights;defaultWorkerWeight;constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.resetWorkerNodeKeyProperties(),this.roundId=0,!0}update(){return!0}choose(){let e,t=this.roundId;for(let s=this.roundId;s<this.roundWeights.length;s++){t=s;for(let t=this.nextWorkerNodeKey??this.previousWorkerNodeKey;t<this.pool.workerNodes.length;t++){const r=this.opts.weights?.[t]??this.defaultWorkerWeight;if(this.isWorkerNodeEligible(t)&&r>=this.roundWeights[s]){e=t;break}}}this.roundId=t,null==e&&(this.previousWorkerNodeKey=this.nextWorkerNodeKey??this.previousWorkerNodeKey),this.nextWorkerNodeKey=e;const s=this.nextWorkerNodeKey;return this.nextWorkerNodeKey===this.pool.workerNodes.length-1?(this.nextWorkerNodeKey=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeKey=(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,s}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+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 M extends F{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:T};constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.nextWorkerNodeKey=this.leastBusyNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastBusyNextWorkerNodeKey(){let e,t=1/0;for(const[s,r]of this.pool.workerNodes.entries()){const i=(r.usage.runTime?.aggregate??0)+(r.usage.waitTime?.aggregate??0);if(this.isWorkerNodeEligible(s)&&0===i){e=s;break}this.isWorkerNodeEligible(s)&&i<t&&(t=i,e=s)}return e}}class K extends F{constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.nextWorkerNodeKey=this.leastUsedNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastUsedNextWorkerNodeKey(){let e,t=1/0;for(const[s,r]of this.pool.workerNodes.entries()){const i=r.usage.tasks,o=i.executed+i.executing+i.queued;if(this.isWorkerNodeEligible(s)&&0===o){e=s;break}this.isWorkerNodeEligible(s)&&o<t&&(t=o,e=s)}return e}}class Q extends F{taskStatisticsRequirements={runTime:T,waitTime:T,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){return this.nextWorkerNodeKey=this.leastEluNextWorkerNodeKey(),this.nextWorkerNodeKey}remove(){return!0}leastEluNextWorkerNodeKey(){let e,t=1/0;for(const[s,r]of this.pool.workerNodes.entries()){const i=r.usage,o=i.elu?.active?.aggregate??0;if(this.isWorkerNodeEligible(s)&&0===o){e=s;break}this.isWorkerNodeEligible(s)&&o<t&&(t=o,e=s)}return e}}class A extends F{constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.resetWorkerNodeKeyProperties(),!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.roundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeEligibility(e),e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=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 P extends F{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:T,elu:T};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=f){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.resetWorkerNodeKeyProperties(),this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeKey;return this.weightedRoundRobinNextWorkerNodeKey(),this.checkNextWorkerNodeEligibility(e),e}remove(e){return this.nextWorkerNodeKey===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeKey=0:this.nextWorkerNodeKey>this.pool.workerNodes.length-1&&(this.nextWorkerNodeKey=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}weightedRoundRobinNextWorkerNodeKey(){const e=this.workerVirtualTaskRunTime;return e<(this.opts.weights?.[this.nextWorkerNodeKey??this.previousWorkerNodeKey]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=e+this.getWorkerTaskRunTime(this.nextWorkerNodeKey??this.previousWorkerNodeKey):(this.nextWorkerNodeKey=this.nextWorkerNodeKey===this.pool.workerNodes.length-1?0:(this.nextWorkerNodeKey??this.previousWorkerNodeKey)+1,this.workerVirtualTaskRunTime=0),this.nextWorkerNodeKey}}class q{workerChoiceStrategy;opts;workerChoiceStrategies;choiceRetriesCount=0;constructor(e,t=v.ROUND_ROBIN,s=f){this.workerChoiceStrategy=t,this.opts=s,this.opts={...f,...s},this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[v.ROUND_ROBIN,new(A.bind(this))(e,s)],[v.LEAST_USED,new(K.bind(this))(e,s)],[v.LEAST_BUSY,new(M.bind(this))(e,s)],[v.LEAST_ELU,new(Q.bind(this))(e,s)],[v.FAIR_SHARE,new(z.bind(this))(e,s)],[v.WEIGHTED_ROUND_ROBIN,new(P.bind(this))(e,s)],[v.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(O.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.choiceRetriesCount<this.opts.choiceRetries)return this.choiceRetriesCount++,this.execute();if(null==e)throw new Error(`Worker node key chosen is null or undefined after ${this.choiceRetriesCount} retries`);return this.choiceRetriesCount=0,e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){this.opts={...f,...e};for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class U 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 U(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 B{items;offset;size;maxSize;constructor(){this.clear()}enqueue(e){return this.items.push(e),++this.size,this.size>this.maxSize&&(this.maxSize=this.size),this.size}dequeue(){if(this.size<=0)return;const e=this.items[this.offset];return 2*++this.offset>=this.items.length&&(this.items=this.items.slice(this.offset),this.offset=0),--this.size,e}peek(){if(!(this.size<=0))return this.items[this.offset]}clear(){this.items=[],this.offset=0,this.size=0,this.maxSize=0}[Symbol.iterator](){const e=this.items;let t=this.offset;return{next:()=>{if(t>=e.length)return{value:void 0,done:!0};const s=e[t];return++t,{value:s,done:!1}}}}}const D=Object.freeze({thread:"thread",cluster:"cluster"});class L{worker;info;messageChannel;usage;taskFunctionsUsage;tasksQueue;tasksQueueBackPressureSize;constructor(e,s,r){if(null==e)throw new TypeError("Cannot construct a worker node without a worker");if(null==s)throw new TypeError("Cannot construct a worker node without a worker type");if(null==r)throw new TypeError("Cannot construct a worker node without a pool maximum size");if(!Number.isSafeInteger(r))throw new TypeError("Cannot construct a worker node with a pool maximum size that is not an integer");this.worker=e,this.info=this.initWorkerInfo(e,s),s===D.thread&&(this.messageChannel=new t),this.usage=this.initWorkerUsage(),this.taskFunctionsUsage=new Map,this.tasksQueue=new B,this.tasksQueueBackPressureSize=Math.pow(r,2)}tasksQueueSize(){return this.tasksQueue.size}tasksQueueMaxSize(){return this.tasksQueue.maxSize}enqueueTask(e){return this.tasksQueue.enqueue(e)}dequeueTask(){return this.tasksQueue.dequeue()}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.taskFunctions))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.taskFunctions)&&this.info.taskFunctions.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===w&&(e=this.info.taskFunctions[1]),this.taskFunctionsUsage.has(e)||this.taskFunctionsUsage.set(e,this.initTaskFunctionWorkerUsage(e)),this.taskFunctionsUsage.get(e)}initWorkerInfo(e,t){return{id:this.getWorkerId(e,t),type:t,dynamic:!1,ready:!1}}initWorkerUsage(){const e=()=>this.tasksQueueSize(),t=()=>this.tasksQueueMaxSize();return{tasks:{executed:0,executing:0,get queued(){return e()},get maxQueued(){return t()},failed:0},runTime:{history:new U},waitTime:{history:new U},elu:{idle:{history:new U},active:{history:new U}}}}initTaskFunctionWorkerUsage(e){const t=()=>{let t=0;for(const s of this.tasksQueue)(s.name===w&&e===this.info.taskFunctions[1]||s.name!==w&&e===s.name)&&++t;return t};return{tasks:{executed:0,executing:0,get queued(){return t()},failed:0},runTime:{history:new U},waitTime:{history:new U},elu:{idle:{history:new U},active:{history:new U}}}}getWorkerId(e,t){return t===D.thread?e.threadId:t===D.cluster?e.id:void 0}}class _{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;max;starting;startTimestamp;constructor(e,t,s){if(this.numberOfWorkers=e,this.filePath=t,this.opts=s,!this.isMain())throw new Error("Cannot start a pool from a worker with the same type as the pool");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),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 m),this.workerChoiceStrategyContext=new q(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook(),this.starting=!0,this.startPool(),this.starting=!1,this.startTimestamp=u.now()}checkFilePath(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(!k(e))throw new Error(`Cannot find the worker file '${e}'`)}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===g.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkDynamicPoolSize(e,t){if(this.type===g.dynamic){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")}}checkPoolOptions(e){if(!S(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??v.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions={...f,...e.workerChoiceStrategyOptions},this.checkValidWorkerChoiceStrategyOptions(this.opts.workerChoiceStrategyOptions),this.opts.restartWorkerOnError=e.restartWorkerOnError??!0,this.opts.enableEvents=e.enableEvents??!0,this.opts.enableTasksQueue=e.enableTasksQueue??!1,this.opts.enableTasksQueue&&(this.checkValidTasksQueueOptions(e.tasksQueueOptions),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e.tasksQueueOptions))}checkValidWorkerChoiceStrategy(e){if(!Object.values(v).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!S(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.choiceRetries&&!Number.isSafeInteger(e.choiceRetries))throw new TypeError("Invalid worker choice strategy options: choice retries must be an integer");if(null!=e.choiceRetries&&e.choiceRetries<=0)throw new RangeError(`Invalid worker choice strategy options: choice retries '${e.choiceRetries}' must be greater 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(R).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(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 tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new RangeError(`Invalid worker tasks concurrency: ${e.concurrency} is a negative integer or zero`)}startPool(){for(;this.workerNodes.reduce(((e,t)=>t.info.dynamic?e:e+1),0)<this.numberOfWorkers;)this.createAndSetupWorkerNode()}get info(){return{version:"2.6.31",type:this.type,worker:this.worker,ready:this.ready,strategy:this.opts.workerChoiceStrategy,minSize:this.minSize,maxSize:this.maxSize,...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{utilization:x(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()},failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:x(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:x(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:x(this.workerNodes.reduce(((e,t)=>e+(t.usage.runTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&{median:x(N(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:x(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:x(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:x(this.workerNodes.reduce(((e,t)=>e+(t.usage.waitTime?.aggregate??0)),0)/this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.executed??0)),0)),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&{median:x(N(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get ready(){return this.workerNodes.reduce(((e,t)=>!t.info.dynamic&&t.info.ready?e+1:e),0)>=this.minSize}get utilization(){const e=(u.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){this.checkValidWorkerChoiceStrategy(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={...f,...e},this.workerChoiceStrategyContext.setOptions(this.opts.workerChoiceStrategyOptions)}enableTasksQueue(e,t){!0!==this.opts.enableTasksQueue||e||this.flushTasksQueues(),this.opts.enableTasksQueue=e,this.setTasksQueueOptions(t)}setTasksQueueOptions(e){!0===this.opts.enableTasksQueue?(this.checkValidTasksQueueOptions(e),this.opts.tasksQueueOptions=this.buildTasksQueueOptions(e)):null!=this.opts.tasksQueueOptions&&delete this.opts.tasksQueueOptions}buildTasksQueueOptions(e){return{concurrency:e?.concurrency??1}}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))}listTaskFunctions(){for(const e of this.workerNodes)if(Array.isArray(e.info.taskFunctions)&&e.info.taskFunctions.length>0)return e.info.taskFunctions;return[]}async execute(e,t,s){return await new Promise(((r,i)=>{null!=t&&"string"!=typeof t&&i(new TypeError("name argument must be a string")),null!=t&&"string"==typeof t&&0===t.trim().length&&i(new TypeError("name argument must not be an empty string")),null==s||Array.isArray(s)||i(new TypeError("transferList argument must be an array"));const o=u.now(),n=this.chooseWorkerNode(),a=this.getWorkerInfo(n);null!=t&&Array.isArray(a.taskFunctions)&&!a.taskFunctions.includes(t)&&i(new Error(`Task function '${t}' is not registered in the pool`));const k={name:t??w,data:e??{},transferList:s,timestamp:o,workerId:a.id,taskId:h()};this.promiseResponseMap.set(k.taskId,{resolve:r,reject:i,workerNodeKey:n}),!1===this.opts.enableTasksQueue||!0===this.opts.enableTasksQueue&&this.workerNodes[n].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency?this.executeTask(n,k):this.enqueueTask(n,k)}))}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{await this.destroyWorkerNode(t)}))),this.emitter?.emit(p.destroy,this.info)}async sendKillMessageToWorker(e,t){await new Promise(((s,r)=>{this.registerWorkerMessageListener(e,(e=>{"success"===e.kill?s():"failure"===e.kill&&r(new Error(`Worker ${t} kill message handling failed`))})),this.sendToWorker(e,{kill:!0,workerId:t})}))}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??w);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.taskFunctions)&&t.taskFunctions.length>2}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;if(null!=s.executing&&s.executing>0)--s.executing;else if(null!=s.executing&&s.executing<0)throw new Error("Worker usage statistic for tasks executing cannot be negative");null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){I(e.runTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime,t.taskPerformance?.runTime??0,e.tasks.executed)}updateWaitTimeWorkerUsage(e,t){const s=u.now(),r=s-(t.timestamp??s);I(e.waitTime,this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime,r,e.tasks.executed)}updateEluWorkerUsage(e,t){const s=this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu;I(e.elu.active,s,t.taskPerformance?.elu?.active??0,e.tasks.executed),I(e.elu.idle,s,t.taskPerformance?.elu?.idle??0,e.tasks.executed),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===g.dynamic&&!this.full&&this.internalBusy()}createAndSetupWorkerNode(){const e=this.createWorker();e.on("online",this.opts.onlineHandler??y),e.on("message",this.opts.messageHandler??y),e.on("error",this.opts.errorHandler??y),e.on("error",(t=>{const s=this.getWorkerNodeKeyByWorker(e),r=this.getWorkerInfo(s);r.ready=!1,this.workerNodes[s].closeChannel(),this.emitter?.emit(p.error,t),!0!==this.opts.restartWorkerOnError||this.starting||(r.dynamic?this.createAndSetupDynamicWorkerNode():this.createAndSetupWorkerNode()),!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(s)})),e.on("exit",this.opts.exitHandler??y),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=>{const t=this.getWorkerNodeKeyByWorkerId(e.workerId),s=this.workerNodes[t].usage;(E(C.HARD,e.kill)||E(C.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(p.error,e)}))}));const t=this.getWorkerInfo(e);return this.sendToWorker(e,{checkActive:!0,workerId:t.id}),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)}sendStatisticsMessageToWorker(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(e).id})}redistributeQueuedTasks(e){for(;this.tasksQueueSize(e)>0;){let t=e,s=1/0,r=!1;for(const[i,o]of this.workerNodes.entries()){const n=this.getWorkerInfo(i);if(i!==e&&n.ready&&0===o.usage.tasks.queued){this.workerNodes[i].usage.tasks.executing<this.opts.tasksQueueOptions?.concurrency&&(r=!0),t=i;break}i!==e&&n.ready&&o.usage.tasks.queued<s&&(s=o.usage.tasks.queued,t=i)}r?this.executeTask(t,this.dequeueTask(e)):this.enqueueTask(t,this.dequeueTask(e))}}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.taskFunctions?this.handleWorkerReadyResponse(e):null!=e.taskId?this.handleTaskExecutionResponse(e):null!=e.taskFunctions&&(this.getWorkerInfo(this.getWorkerNodeKeyByWorkerId(e.workerId)).taskFunctions=e.taskFunctions)}}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.taskFunctions=e.taskFunctions,null!=this.emitter&&this.ready&&this.emitter.emit(p.ready,this.info)}handleTaskExecutionResponse(e){const{taskId:t,taskError:s,data:r}=e,i=this.promiseResponseMap.get(t);if(null!=i){null!=s?(this.emitter?.emit(p.taskError,s),i.reject(s.message)):i.resolve(r);const o=i.workerNodeKey;this.afterTaskExecutionHook(o,e),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)),this.workerChoiceStrategyContext.update(o)}}checkAndEmitTaskExecutionEvents(){this.busy&&this.emitter?.emit(p.busy,this.info)}checkAndEmitTaskQueuingEvents(){this.hasBackPressure()&&this.emitter?.emit(p.backPressure,this.info)}checkAndEmitDynamicWorkerCreationEvents(){this.type===g.dynamic&&this.full&&this.emitter?.emit(p.full,this.info)}getWorkerInfo(e){return this.workerNodes[e]?.info}addWorkerNode(e){const t=new L(e,this.worker,this.maxSize);this.starting&&(t.info.ready=!0),this.workerNodes.push(t);const s=this.getWorkerNodeKeyByWorker(e);if(-1===s)throw new Error("Worker node added not found");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 V extends _{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){a.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return a.isPrimary}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e].worker,s=new Promise((e=>{t.on("exit",(()=>{e()}))}));t.on("disconnect",(()=>{t.kill()})),await this.sendKillMessageToWorker(e,t.id),t.disconnect(),await s}sendToWorker(e,t){this.workerNodes[e].worker.send(t)}sendStartupMessageToWorker(e){this.sendToWorker(e,{ready:!1,workerId:this.workerNodes[e].worker.id})}registerWorkerMessageListener(e,t){this.workerNodes[e].worker.on("message",t)}createWorker(){return a.fork(this.opts.env)}get type(){return g.fixed}get worker(){return D.cluster}get busy(){return this.internalBusy()}}class j extends V{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return g.dynamic}get busy(){return this.full&&this.internalBusy()}}class H extends _{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return s}async destroyWorkerNode(e){this.flushTasksQueue(e);const t=this.workerNodes[e],s=t.worker,r=new Promise((e=>{s.on("exit",(()=>{e()}))}));await this.sendKillMessageToWorker(e,s.threadId),t.closeChannel(),await s.terminate(),await r}sendToWorker(e,t,s){this.workerNodes[e].messageChannel.port1.postMessage(t,s)}sendStartupMessageToWorker(e){const t=this.workerNodes[e].worker,s=this.workerNodes[e].messageChannel.port2;t.postMessage({ready:!1,workerId:t.threadId,port:s},[s])}registerWorkerMessageListener(e,t){this.workerNodes[e].messageChannel.port1.on("message",t)}createWorker(){return new r(this.filePath,{env:i,...this.opts.workerOptions})}get type(){return g.fixed}get worker(){return D.thread}get busy(){return this.internalBusy()}}class $ extends H{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return g.dynamic}get busy(){return this.full&&this.internalBusy()}}const G=6e4,Y={killBehavior:C.SOFT,maxInactiveTime:G,killHandler:y};class J extends l{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;activeInterval;constructor(e,t,s,r,i=Y){super(e),this.isMain=t,this.mainWorker=s,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(r),this.isMain||this.getMainWorker()?.on("message",this.handleReadyMessage.bind(this))}checkWorkerOptions(e){this.opts={...Y,...e},delete this.opts.async}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(w,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)){if("string"!=typeof s)throw new TypeError("A taskFunctions parameter object key is not a string");if("string"==typeof s&&0===s.trim().length)throw new TypeError("A taskFunctions parameter object key an empty string");if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");const e=r.bind(this);t&&(this.taskFunctions.set(w,e),t=!1),this.taskFunctions.set(s,e)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){return this.checkTaskFunctionName(e),this.taskFunctions.has(e)}addTaskFunction(e,t){if(this.checkTaskFunctionName(e),e===w)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");try{const s=t.bind(this);return this.taskFunctions.get(e)===this.taskFunctions.get(w)&&this.taskFunctions.set(w,s),this.taskFunctions.set(e,s),this.sendTaskFunctionsListToMainWorker(),!0}catch{return!1}}removeTaskFunction(e){if(this.checkTaskFunctionName(e),e===w)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(w))throw new Error("Cannot remove the task function used as the default task function");const t=this.taskFunctions.delete(e);return this.sendTaskFunctionsListToMainWorker(),t}listTaskFunctions(){const e=[...this.taskFunctions.keys()];let t=w;for(const[e,s]of this.taskFunctions)if(e!==w&&s===this.taskFunctions.get(w)){t=e;break}return[e[e.indexOf(w)],t,...e.filter((e=>e!==w&&e!==t))]}setDefaultTaskFunction(e){if(this.checkTaskFunctionName(e),e===w)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");try{return this.taskFunctions.set(w,this.taskFunctions.get(e)),!0}catch{return!1}}checkTaskFunctionName(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")}messageListener(e){this.checkMessageWorkerId(e),null!=e.statistics?this.statistics=e.statistics:null!=e.checkActive?e.checkActive?this.startCheckActive():this.stopCheckActive():null!=e.taskId&&null!=e.data?this.run(e):!0===e.kill&&this.handleKillMessage(e)}handleKillMessage(e){if(this.stopCheckActive(),b(this.opts.killHandler))(this.opts.killHandler?.()).then((()=>(this.sendToMainWorker({kill:"success",workerId:this.id}),null))).catch((()=>{this.sendToMainWorker({kill:"failure",workerId:this.id})})).finally((()=>{this.emitDestroy()})).catch(y);else try{this.opts.killHandler?.(),this.sendToMainWorker({kill:"success",workerId:this.id})}catch{this.sendToMainWorker({kill:"failure",workerId:this.id})}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=u.now(),this.activeInterval=setInterval(this.checkActive.bind(this),(this.opts.maxInactiveTime??G)/2)}stopCheckActive(){null!=this.activeInterval&&(clearInterval(this.activeInterval),delete this.activeInterval)}checkActive(){u.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??G)&&this.sendToMainWorker({kill:this.opts.killBehavior,workerId:this.id})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}sendTaskFunctionsListToMainWorker(){this.sendToMainWorker({taskFunctions:this.listTaskFunctions(),workerId:this.id})}handleError(e){return e instanceof Error?e.message:e}run(e){const t=this.getTaskFunction(e.name);b(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}runSync(e,t){const{name:s,taskId:r,data:i}=t;try{let t=this.beginTaskPerformance(s);const o=e(i);t=this.endTaskPerformance(t),this.sendToMainWorker({data:o,taskPerformance:t,workerId:this.id,taskId:r})}catch(e){const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??w,message:t,data:i},workerId:this.id,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,workerId:this.id,taskId:r}),null))).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({taskError:{name:s??w,message:t,data:i},workerId:this.id,taskId:r})})).finally((()=>{this.updateLastTaskTimestamp()})).catch(y)}getTaskFunction(e){e=e??w;const t=this.taskFunctions.get(e);if(null==t)throw new Error(`Task function '${e}' not found`);return t}beginTaskPerformance(e){return this.checkStatistics(),{name:e??w,timestamp:u.now(),...this.statistics.elu&&{elu:u.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:u.now()-e.timestamp},...this.statistics.elu&&{elu:u.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}updateLastTaskTimestamp(){null!=this.activeInterval&&(this.lastTaskTimestamp=u.now())}}class X extends J{constructor(e,t={}){super("worker-cluster-pool:poolifier",a.isPrimary,a.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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}}class Z extends J{port;constructor(e,t={}){super("worker-thread-pool:poolifier",s,o,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,taskFunctions:this.listTaskFunctions(),workerId:this.id})}catch{this.sendToMainWorker({ready:!1,taskFunctions:this.listTaskFunctions(),workerId:this.id})}}handleKillMessage(e){super.handleKillMessage(e),this.port?.unref(),this.port?.close()}get id(){return n}sendToMainWorker(e){this.port.postMessage(e)}handleError(e){return e}}export{X as ClusterWorker,j as DynamicClusterPool,$ as DynamicThreadPool,V as FixedClusterPool,H as FixedThreadPool,C as KillBehaviors,R as Measurements,p as PoolEvents,g as PoolTypes,Z as ThreadWorker,v as WorkerChoiceStrategies,D as WorkerTypes,W as availableParallelism};
@@ -274,7 +274,7 @@ export declare abstract class AbstractPool<Worker extends IWorker, Data = unknow
274
274
  * @param workerNodeKey - The worker node key.
275
275
  * @returns The worker information.
276
276
  */
277
- protected getWorkerInfo(workerNodeKey: number): WorkerInfo;
277
+ protected getWorkerInfo(workerNodeKey: number): WorkerInfo | undefined;
278
278
  /**
279
279
  * Adds the given worker in the pool worker nodes.
280
280
  *
@@ -14,7 +14,11 @@ export declare abstract class AbstractWorkerChoiceStrategy<Worker extends IWorke
14
14
  /**
15
15
  * The next worker node key.
16
16
  */
17
- protected nextWorkerNodeKey: number;
17
+ protected nextWorkerNodeKey: number | undefined;
18
+ /**
19
+ * The previous worker node key.
20
+ */
21
+ protected previousWorkerNodeKey: number;
18
22
  /** @inheritDoc */
19
23
  readonly strategyPolicy: StrategyPolicy;
20
24
  /** @inheritDoc */
@@ -28,12 +32,13 @@ export declare abstract class AbstractWorkerChoiceStrategy<Worker extends IWorke
28
32
  constructor(pool: IPool<Worker, Data, Response>, opts?: WorkerChoiceStrategyOptions);
29
33
  protected setTaskStatisticsRequirements(opts: WorkerChoiceStrategyOptions): void;
30
34
  private toggleMedianMeasurementStatisticsRequirements;
35
+ protected resetWorkerNodeKeyProperties(): void;
31
36
  /** @inheritDoc */
32
37
  abstract reset(): boolean;
33
38
  /** @inheritDoc */
34
39
  abstract update(workerNodeKey: number): boolean;
35
40
  /** @inheritDoc */
36
- abstract choose(): number;
41
+ abstract choose(): number | undefined;
37
42
  /** @inheritDoc */
38
43
  abstract remove(workerNodeKey: number): boolean;
39
44
  /** @inheritDoc */
@@ -89,5 +94,11 @@ export declare abstract class AbstractWorkerChoiceStrategy<Worker extends IWorke
89
94
  * @returns The worker task ELU.
90
95
  */
91
96
  protected getWorkerTaskElu(workerNodeKey: number): number;
97
+ /**
98
+ * Check the next worker node eligibility.
99
+ *
100
+ * @param chosenWorkerNodeKey - The chosen worker node key.
101
+ */
102
+ protected checkNextWorkerNodeEligibility(chosenWorkerNodeKey: number | undefined): void;
92
103
  protected computeDefaultWorkerWeight(): number;
93
104
  }
@@ -24,7 +24,7 @@ export declare class FairShareWorkerChoiceStrategy<Worker extends IWorker, Data
24
24
  /** @inheritDoc */
25
25
  update(workerNodeKey: number): boolean;
26
26
  /** @inheritDoc */
27
- choose(): number;
27
+ choose(): number | undefined;
28
28
  /** @inheritDoc */
29
29
  remove(workerNodeKey: number): boolean;
30
30
  private fairShareNextWorkerNodeKey;
@@ -1,7 +1,7 @@
1
1
  import type { IWorker } from '../worker';
2
2
  import type { IPool } from '../pool';
3
3
  import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy';
4
- import type { IWorkerChoiceStrategy, StrategyPolicy, WorkerChoiceStrategyOptions } from './selection-strategies-types';
4
+ import type { IWorkerChoiceStrategy, WorkerChoiceStrategyOptions } from './selection-strategies-types';
5
5
  /**
6
6
  * Selects the next worker with an interleaved weighted round robin scheduling algorithm.
7
7
  *
@@ -10,8 +10,6 @@ import type { IWorkerChoiceStrategy, StrategyPolicy, WorkerChoiceStrategyOptions
10
10
  * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
11
11
  */
12
12
  export declare class InterleavedWeightedRoundRobinWorkerChoiceStrategy<Worker extends IWorker, Data = unknown, Response = unknown> extends AbstractWorkerChoiceStrategy<Worker, Data, Response> implements IWorkerChoiceStrategy {
13
- /** @inheritDoc */
14
- readonly strategyPolicy: StrategyPolicy;
15
13
  /**
16
14
  * Round id.
17
15
  * This is used to determine the current round weight.
@@ -32,7 +30,7 @@ export declare class InterleavedWeightedRoundRobinWorkerChoiceStrategy<Worker ex
32
30
  /** @inheritDoc */
33
31
  update(): boolean;
34
32
  /** @inheritDoc */
35
- choose(): number;
33
+ choose(): number | undefined;
36
34
  /** @inheritDoc */
37
35
  remove(workerNodeKey: number): boolean;
38
36
  /** @inheritDoc */
@@ -19,7 +19,7 @@ export declare class LeastBusyWorkerChoiceStrategy<Worker extends IWorker, Data
19
19
  /** @inheritDoc */
20
20
  update(): boolean;
21
21
  /** @inheritDoc */
22
- choose(): number;
22
+ choose(): number | undefined;
23
23
  /** @inheritDoc */
24
24
  remove(): boolean;
25
25
  private leastBusyNextWorkerNodeKey;
@@ -19,7 +19,7 @@ export declare class LeastEluWorkerChoiceStrategy<Worker extends IWorker, Data =
19
19
  /** @inheritDoc */
20
20
  update(): boolean;
21
21
  /** @inheritDoc */
22
- choose(): number;
22
+ choose(): number | undefined;
23
23
  /** @inheritDoc */
24
24
  remove(): boolean;
25
25
  private leastEluNextWorkerNodeKey;
@@ -17,7 +17,7 @@ export declare class LeastUsedWorkerChoiceStrategy<Worker extends IWorker, Data
17
17
  /** @inheritDoc */
18
18
  update(): boolean;
19
19
  /** @inheritDoc */
20
- choose(): number;
20
+ choose(): number | undefined;
21
21
  /** @inheritDoc */
22
22
  remove(): boolean;
23
23
  private leastUsedNextWorkerNodeKey;
@@ -1,7 +1,7 @@
1
1
  import type { IPool } from '../pool';
2
2
  import type { IWorker } from '../worker';
3
3
  import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy';
4
- import type { IWorkerChoiceStrategy, StrategyPolicy, WorkerChoiceStrategyOptions } from './selection-strategies-types';
4
+ import type { IWorkerChoiceStrategy, WorkerChoiceStrategyOptions } from './selection-strategies-types';
5
5
  /**
6
6
  * Selects the next worker in a round robin fashion.
7
7
  *
@@ -10,8 +10,6 @@ import type { IWorkerChoiceStrategy, StrategyPolicy, WorkerChoiceStrategyOptions
10
10
  * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
11
11
  */
12
12
  export declare class RoundRobinWorkerChoiceStrategy<Worker extends IWorker, Data = unknown, Response = unknown> extends AbstractWorkerChoiceStrategy<Worker, Data, Response> implements IWorkerChoiceStrategy {
13
- /** @inheritDoc */
14
- readonly strategyPolicy: StrategyPolicy;
15
13
  /** @inheritDoc */
16
14
  constructor(pool: IPool<Worker, Data, Response>, opts?: WorkerChoiceStrategyOptions);
17
15
  /** @inheritDoc */
@@ -19,7 +17,7 @@ export declare class RoundRobinWorkerChoiceStrategy<Worker extends IWorker, Data
19
17
  /** @inheritDoc */
20
18
  update(): boolean;
21
19
  /** @inheritDoc */
22
- choose(): number;
20
+ choose(): number | undefined;
23
21
  /** @inheritDoc */
24
22
  remove(workerNodeKey: number): boolean;
25
23
  private roundRobinNextWorkerNodeKey;
@@ -16,8 +16,6 @@ export declare const WorkerChoiceStrategies: Readonly<{
16
16
  readonly LEAST_BUSY: "LEAST_BUSY";
17
17
  /**
18
18
  * Least ELU worker selection strategy.
19
- *
20
- * @experimental
21
19
  */
22
20
  readonly LEAST_ELU: "LEAST_ELU";
23
21
  /**
@@ -145,9 +143,13 @@ export interface TaskStatisticsRequirements {
145
143
  */
146
144
  export interface StrategyPolicy {
147
145
  /**
148
- * Expects direct usage of the newly created dynamic worker.
146
+ * Expects tasks execution on the newly created dynamic worker.
147
+ */
148
+ readonly dynamicWorkerUsage: boolean;
149
+ /**
150
+ * Expects the newly created dynamic worker to be flagged as ready.
149
151
  */
150
- readonly useDynamicWorker: boolean;
152
+ readonly dynamicWorkerReady: boolean;
151
153
  }
152
154
  /**
153
155
  * Worker choice strategy interface.
@@ -177,10 +179,11 @@ export interface IWorkerChoiceStrategy {
177
179
  readonly update: (workerNodeKey: number) => boolean;
178
180
  /**
179
181
  * Chooses a worker node in the pool and returns its key.
182
+ * If the worker node is not eligible, `undefined` is returned.
180
183
  *
181
- * @returns The worker node key.
184
+ * @returns The worker node key or `undefined`.
182
185
  */
183
- readonly choose: () => number;
186
+ readonly choose: () => number | undefined;
184
187
  /**
185
188
  * Removes the worker node key from strategy internals.
186
189
  *
@@ -1,7 +1,7 @@
1
1
  import type { IWorker } from '../worker';
2
2
  import type { IPool } from '../pool';
3
3
  import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy';
4
- import type { IWorkerChoiceStrategy, StrategyPolicy, TaskStatisticsRequirements, WorkerChoiceStrategyOptions } from './selection-strategies-types';
4
+ import type { IWorkerChoiceStrategy, TaskStatisticsRequirements, WorkerChoiceStrategyOptions } from './selection-strategies-types';
5
5
  /**
6
6
  * Selects the next worker with a weighted round robin scheduling algorithm.
7
7
  * Loosely modeled after the weighted round robin queueing algorithm: https://en.wikipedia.org/wiki/Weighted_round_robin.
@@ -11,8 +11,6 @@ import type { IWorkerChoiceStrategy, StrategyPolicy, TaskStatisticsRequirements,
11
11
  * @typeParam Response - Type of execution response. This can only be structured-cloneable data.
12
12
  */
13
13
  export declare class WeightedRoundRobinWorkerChoiceStrategy<Worker extends IWorker, Data = unknown, Response = unknown> extends AbstractWorkerChoiceStrategy<Worker, Data, Response> implements IWorkerChoiceStrategy {
14
- /** @inheritDoc */
15
- readonly strategyPolicy: StrategyPolicy;
16
14
  /** @inheritDoc */
17
15
  readonly taskStatisticsRequirements: TaskStatisticsRequirements;
18
16
  /**
@@ -30,7 +28,7 @@ export declare class WeightedRoundRobinWorkerChoiceStrategy<Worker extends IWork
30
28
  /** @inheritDoc */
31
29
  update(): boolean;
32
30
  /** @inheritDoc */
33
- choose(): number;
31
+ choose(): number | undefined;
34
32
  /** @inheritDoc */
35
33
  remove(workerNodeKey: number): boolean;
36
34
  private weightedRoundRobinNextWorkerNodeKey;
@@ -52,7 +52,7 @@ export declare class WorkerChoiceStrategyContext<Worker extends IWorker, Data =
52
52
  * Executes the worker choice strategy in the context algorithm.
53
53
  *
54
54
  * @returns The key of the worker node.
55
- * @throws {@link https://nodejs.org/api/errors.html#class-error} If the worker node key is null or undefined.
55
+ * @throws {@link https://nodejs.org/api/errors.html#class-error} If after configured retries the worker node key is null or undefined .
56
56
  */
57
57
  execute(): number;
58
58
  /**
@@ -1 +1 @@
1
- export declare const version = "2.6.30";
1
+ export declare const version = "2.6.31";
@@ -188,7 +188,7 @@ export interface IWorkerNode<Worker extends IWorker, Data = unknown> {
188
188
  */
189
189
  readonly info: WorkerInfo;
190
190
  /**
191
- * Message channel.
191
+ * Message channel (worker_threads only).
192
192
  */
193
193
  readonly messageChannel?: MessageChannel;
194
194
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "poolifier",
4
- "version": "2.6.30",
4
+ "version": "2.6.31",
5
5
  "description": "Fast and small Node.js Worker_Threads and Cluster Worker Pool",
6
6
  "license": "MIT",
7
7
  "main": "./lib/index.js",
@@ -86,13 +86,13 @@
86
86
  "@rollup/plugin-terser": "^0.4.3",
87
87
  "@rollup/plugin-typescript": "^11.1.2",
88
88
  "@types/node": "^20.5.1",
89
- "@typescript-eslint/eslint-plugin": "^5.62.0",
90
- "@typescript-eslint/parser": "^5.62.0",
89
+ "@typescript-eslint/eslint-plugin": "^6.4.0",
90
+ "@typescript-eslint/parser": "^6.4.0",
91
91
  "benny": "^3.7.1",
92
92
  "c8": "^8.0.1",
93
93
  "eslint": "^8.47.0",
94
94
  "eslint-config-standard": "^17.1.0",
95
- "eslint-config-standard-with-typescript": "^37.0.0",
95
+ "eslint-config-standard-with-typescript": "^38.0.0",
96
96
  "eslint-define-config": "^1.23.0",
97
97
  "eslint-import-resolver-typescript": "^3.6.0",
98
98
  "eslint-plugin-import": "^2.28.1",