poolifier
Advanced tools
Comparing version 2.6.12 to 2.6.13
@@ -1,1 +0,1 @@ | ||
"use strict";var e=require("node:events"),t=require("node:cluster"),s=require("node:crypto"),r=require("node:perf_hooks"),i=require("node:os"),o=require("node:worker_threads"),a=require("node:async_hooks");function n(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=n(i);const h=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class k extends e.EventEmitter{}const c=Object.freeze({full:"full",ready:"ready",busy:"busy",error:"error",taskError:"taskError"}),d=Object.freeze((()=>{})),m={runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},l={aggregate:!1,average:!1,median:!1},g=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},p=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},w=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),T=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),f=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LEAST_USED:"LEAST_USED",LEAST_BUSY:"LEAST_BUSY",LEAST_ELU:"LEAST_ELU",FAIR_SHARE:"FAIR_SHARE",WEIGHTED_ROUND_ROBIN:"WEIGHTED_ROUND_ROBIN",INTERLEAVED_WEIGHTED_ROUND_ROBIN:"INTERLEAVED_WEIGHTED_ROUND_ROBIN"}),y=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class W{pool;opts;nextWorkerNodeId=0;strategyPolicy={useDynamicWorker:!1};taskStatisticsRequirements={runTime:l,waitTime:l,elu:l};constructor(e,t=m){this.pool=e,this.opts=t,this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.taskStatisticsRequirements.runTime.average&&!0===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!1,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.runTime.median&&!1===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!0,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.waitTime.average&&!0===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!1,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.waitTime.median&&!1===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!0,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.elu.average&&!0===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!1,this.taskStatisticsRequirements.elu.median=e.elu.median),this.taskStatisticsRequirements.elu.median&&!1===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!0,this.taskStatisticsRequirements.elu.median=e.elu.median)}setOptions(e){this.opts=e??m,this.setTaskStatisticsRequirements(this.opts)}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 i.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/i.cpus().length)}}class S extends W{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:l,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(){let e=1/0;for(const[t]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[t]&&this.computeWorkerVirtualTaskEndTimestamp(t);const s=this.workersVirtualTaskEndTimestamp[t];s<e&&(e=s,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===y.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class x extends W{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.nextWorkerNodeId=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.nextWorkerNodeId;r<this.pool.workerNodes.length;r++){if((this.opts.weights?.[r]??this.defaultWorkerWeight)>=this.roundWeights[s]){e=s,t=r;break}}this.roundId=e??0,this.nextWorkerNodeId=t??0;const s=this.nextWorkerNodeId;return this.nextWorkerNodeId===this.pool.workerNodes.length-1?(this.nextWorkerNodeId=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeId=this.nextWorkerNodeId+1,s}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=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 N extends W{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:l};constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===r){this.nextWorkerNodeId=t;break}r<e&&(e=r,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class I extends W{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class v extends W{taskStatisticsRequirements={runTime:l,waitTime:l,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(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage,i=r.elu?.active?.aggregate??0;if(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class E extends W{strategyPolicy={useDynamicWorker:!0};constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.nextWorkerNodeId=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId;return this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1)),!0}}class R extends W{strategyPolicy={useDynamicWorker:!0};taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:l,elu:l};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.nextWorkerNodeId=0,this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId,t=this.workerVirtualTaskRunTime;return t<(this.opts.weights?.[e]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=t+this.getWorkerTaskRunTime(e):(this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,this.workerVirtualTaskRunTime=0),e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}}class b{workerChoiceStrategy;workerChoiceStrategies;constructor(e,t=f.ROUND_ROBIN,s=m){this.workerChoiceStrategy=t,this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[f.ROUND_ROBIN,new(E.bind(this))(e,s)],[f.LEAST_USED,new(I.bind(this))(e,s)],[f.LEAST_BUSY,new(N.bind(this))(e,s)],[f.LEAST_ELU,new(v.bind(this))(e,s)],[f.FAIR_SHARE,new(S.bind(this))(e,s)],[f.WEIGHTED_ROUND_ROBIN,new(R.bind(this))(e,s)],[f.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(x.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)throw new Error("Worker node key chosen is null or undefined");return e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class C 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;return arguments.length>=3&&void 0!==t?(r=super.splice(e,t),this.push(...s)):r=2===arguments.length?super.splice(e,t):super.splice(e),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 O{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}}const z=Object.freeze({cluster:"cluster",thread:"thread"});class q{worker;info;usage;tasksQueue;constructor(e,t){this.worker=e,this.info=this.initWorkerInfo(e,t),this.usage=this.initWorkerUsage(),this.tasksQueue=new O}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()}resetUsage(){this.usage=this.initWorkerUsage()}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 C},waitTime:{history:new C},elu:{idle:{history:new C},active:{history:new C}}}}getWorkerId(e,t){return t===z.thread?e.threadId:t===z.cluster?e.id:void 0}}class M{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;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!");for(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),this.checkAndEmitEvents=this.checkAndEmitEvents.bind(this),!0===this.opts.enableEvents&&(this.emitter=new k),this.workerChoiceStrategyContext=new b(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook();this.workerNodes.length<this.numberOfWorkers;)this.createAndSetupWorker();this.startTimestamp=r.performance.now()}checkFilePath(e){if(null==e||"string"==typeof e&&0===e.trim().length)throw new Error("Please specify a file with a worker implementation")}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new 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===h.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkDynamicPoolSize(e,t){if(this.type===h.dynamic){if(e>t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size");if(0===e&&0===t)throw new RangeError("Cannot instantiate a dynamic pool with a minimum pool size and 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(!w(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??f.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions=e.workerChoiceStrategyOptions??m,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(f).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!w(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e.measurement&&!Object.values(y).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(e){if(null!=e&&!w(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new Error(`Invalid worker tasks concurrency '${e.concurrency}'`)}get info(){return{version:"2.6.12",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:p(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),queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0),maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.maxQueued),0),failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:p(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:p(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:p(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:p(g(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:p(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:p(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:p(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:p(g(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get starting(){return this.workerNodes.length<this.minSize||this.workerNodes.length>=this.minSize&&this.workerNodes.some((e=>!e.info.ready))}get ready(){return this.workerNodes.length>=this.minSize&&this.workerNodes.every((e=>e.info.ready))}get utilization(){const e=(r.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}getWorkerById(e){return this.workerNodes.find((t=>t.info.id===e))?.worker}checkMessageWorkerId(e){if(null!=e.workerId&&null==this.getWorkerById(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKey(e){return this.workerNodes.findIndex((t=>t.worker===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 of this.workerNodes)e.resetUsage(),this.setWorkerStatistics(e.worker)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions=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-1===this.workerNodes.findIndex((e=>0===e.usage.tasks.executing))}async execute(e,t){const i=r.performance.now(),o=this.chooseWorkerNode(),a={name:t,data:e??{},timestamp:i,workerId:this.getWorkerInfo(o).id,id:s.randomUUID()},n=new Promise(((e,t)=>{this.promiseResponseMap.set(a.id,{resolve:e,reject:t,worker:this.workerNodes[o].worker})}));return!0===this.opts.enableTasksQueue&&(this.busy||this.workerNodes[o].usage.tasks.executing>=this.opts.tasksQueueOptions.concurrency)?this.enqueueTask(o,a):this.executeTask(o,a),this.checkAndEmitEvents(),n}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{this.flushTasksQueue(t);const s=new Promise((t=>{e.worker.on("exit",(()=>{t()}))}));await this.destroyWorker(e.worker),await s})))}setupHook(){}beforeTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}afterTaskExecutionHook(e,t){const s=this.workerNodes[this.getWorkerNodeKey(e)].usage;this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;--s.executing,null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){if(this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate){const s=t.taskPerformance?.runTime??0;e.runTime.aggregate=(e.runTime.aggregate??0)+s,e.runTime.minimum=Math.min(s,e.runTime?.minimum??1/0),e.runTime.maximum=Math.max(s,e.runTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&0!==e.tasks.executed&&(e.runTime.average=e.runTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&null!=t.taskPerformance?.runTime&&(e.runTime.history.push(t.taskPerformance.runTime),e.runTime.median=g(e.runTime.history))}}updateWaitTimeWorkerUsage(e,t){const s=r.performance.now(),i=s-(t.timestamp??s);this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&(e.waitTime.aggregate=(e.waitTime?.aggregate??0)+i,e.waitTime.minimum=Math.min(i,e.waitTime?.minimum??1/0),e.waitTime.maximum=Math.max(i,e.waitTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&0!==e.tasks.executed&&(e.waitTime.average=e.waitTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&(e.waitTime.history.push(i),e.waitTime.median=g(e.waitTime.history)))}updateEluWorkerUsage(e,t){this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate&&null!=t.taskPerformance?.elu&&(e.elu.idle.aggregate=(e.elu.idle?.aggregate??0)+t.taskPerformance.elu.idle,e.elu.active.aggregate=(e.elu.active?.aggregate??0)+t.taskPerformance.elu.active,null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization,e.elu.idle.minimum=Math.min(t.taskPerformance.elu.idle,e.elu.idle?.minimum??1/0),e.elu.idle.maximum=Math.max(t.taskPerformance.elu.idle,e.elu.idle?.maximum??-1/0),e.elu.active.minimum=Math.min(t.taskPerformance.elu.active,e.elu.active?.minimum??1/0),e.elu.active.maximum=Math.max(t.taskPerformance.elu.active,e.elu.active?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.average&&0!==e.tasks.executed&&(e.elu.idle.average=e.elu.idle.aggregate/e.tasks.executed,e.elu.active.average=e.elu.active.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.median&&(e.elu.idle.history.push(t.taskPerformance.elu.idle),e.elu.active.history.push(t.taskPerformance.elu.active),e.elu.idle.median=g(e.elu.idle.history),e.elu.active.median=g(e.elu.active.history)))}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorker();if(this.workerChoiceStrategyContext.getStrategyPolicy().useDynamicWorker)return this.getWorkerNodeKey(e)}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===h.dynamic&&!this.full&&this.internalBusy()}registerWorkerMessageListener(e,t){e.on("message",t)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,this.workerListener()),this.sendToWorker(e,{ready:!1,workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id}),this.setWorkerStatistics(e)}createAndSetupWorker(){const e=this.createWorker();return e.on("message",this.opts.messageHandler??d),e.on("error",this.opts.errorHandler??d),e.on("error",(t=>{null!=this.emitter&&this.emitter.emit(c.error,t),!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(e),!0!==this.opts.restartWorkerOnError||this.starting||(this.getWorkerInfo(this.getWorkerNodeKey(e)).dynamic?this.createAndSetupDynamicWorker():this.createAndSetupWorker())})),e.on("online",this.opts.onlineHandler??d),e.on("exit",this.opts.exitHandler??d),e.once("exit",(()=>{this.removeWorkerNode(e)})),this.pushWorkerNode(e),this.afterWorkerSetup(e),e}redistributeQueuedTasks(e){const t=this.getWorkerNodeKey(e);for(;this.tasksQueueSize(t)>0;){let e=t,s=1/0;for(const[r,i]of this.workerNodes.entries()){if(r!==t&&0===i.usage.tasks.queued){e=r;break}r!==t&&i.usage.tasks.queued<s&&(s=i.usage.tasks.queued,e=r)}this.enqueueTask(e,this.dequeueTask(t))}}createAndSetupDynamicWorker(){const e=this.createAndSetupWorker();this.registerWorkerMessageListener(e,(t=>{const s=this.getWorkerNodeKey(e);var r;r=T.HARD,(t.kill===r||null!=t.kill&&(!1===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing||!0===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing&&0===this.tasksQueueSize(s)))&&this.destroyWorker(e)}));const t=this.getWorkerInfo(this.getWorkerNodeKey(e));return t.dynamic=!0,this.sendToWorker(e,{checkAlive:!0,workerId:t.id}),e}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.workerId?this.handleWorkerReadyMessage(e):null!=e.id&&this.handleTaskExecutionResponse(e)}}handleWorkerReadyMessage(e){const t=this.getWorkerById(e.workerId);this.getWorkerInfo(this.getWorkerNodeKey(t)).ready=e.ready,null!=this.emitter&&this.ready&&this.emitter.emit(c.ready,this.info)}handleTaskExecutionResponse(e){const t=this.promiseResponseMap.get(e.id);if(null!=t){null!=e.taskError?(null!=this.emitter&&this.emitter.emit(c.taskError,e.taskError),t.reject(e.taskError.message)):t.resolve(e.data),this.afterTaskExecutionHook(t.worker,e),this.promiseResponseMap.delete(e.id);const s=this.getWorkerNodeKey(t.worker);!0===this.opts.enableTasksQueue&&this.tasksQueueSize(s)>0&&this.executeTask(s,this.dequeueTask(s)),this.workerChoiceStrategyContext.update(s)}}checkAndEmitEvents(){null!=this.emitter&&(this.busy&&this.emitter.emit(c.busy,this.info),this.type===h.dynamic&&this.full&&this.emitter.emit(c.full,this.info))}getWorkerInfo(e){return this.workerNodes[e].info}pushWorkerNode(e){return this.workerNodes.push(new q(e,this.worker))}removeWorkerNode(e){const t=this.getWorkerNodeKey(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}executeTask(e,t){this.beforeTaskExecutionHook(e,t),this.sendToWorker(this.workerNodes[e].worker,t)}enqueueTask(e,t){return this.workerNodes[e].enqueueTask(t)}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)}setWorkerStatistics(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id})}}class P extends M{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){t.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return t.isPrimary}destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.id}),e.on("disconnect",(()=>{e.kill()})),e.disconnect()}sendToWorker(e,t){e.send(t)}createWorker(){return t.fork(this.opts.env)}get type(){return h.fixed}get worker(){return z.cluster}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}class A extends M{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return o.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.threadId}),await e.terminate()}sendToWorker(e,t){e.postMessage(t)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV,...this.opts.workerOptions})}get type(){return h.fixed}get worker(){return z.thread}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}const Q="default",D=6e4,U=T.SOFT;class _ extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;aliveInterval;constructor(e,t,s,r,i={killBehavior:U,maxInactiveTime:D}){super(e),this.isMain=t,this.mainWorker=r,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(s),this.isMain||this.mainWorker?.on("message",this.messageListener.bind(this))}checkWorkerOptions(e){this.opts.killBehavior=e.killBehavior??U,this.opts.maxInactiveTime=e.maxInactiveTime??D,delete this.opts.async}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e)this.taskFunctions.set(Q,e.bind(this));else{if(!w(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");this.taskFunctions.set(s,r.bind(this)),t&&(this.taskFunctions.set(Q,r.bind(this)),t=!1)}if(t)throw new Error("taskFunctions parameter object is empty")}}}messageListener(e){if(null!=e.ready&&e.workerId===this.id)this.workerReady();else if(null!=e.statistics&&e.workerId===this.id)this.statistics=e.statistics;else if(null!=e.checkAlive&&e.workerId===this.id)e.checkAlive?this.startCheckAlive():this.stopCheckAlive();else if(null!=e.id&&null!=e.data&&e.workerId===this.id){const t=this.getTaskFunction(e.name);(e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name)(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}else!0===e.kill&&e.workerId===this.id&&(this.stopCheckAlive(),this.emitDestroy())}workerReady(){!this.isMain&&this.sendToMainWorker({ready:!0,workerId:this.id})}startCheckAlive(){this.lastTaskTimestamp=r.performance.now(),this.aliveInterval=setInterval(this.checkAlive.bind(this),(this.opts.maxInactiveTime??D)/2),this.checkAlive.bind(this)()}stopCheckAlive(){null!=this.aliveInterval&&clearInterval(this.aliveInterval)}checkAlive(){r.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}handleError(e){return e instanceof Error?e.message:e}runSync(e,t){try{let s=this.beginTaskPerformance();const r=e(t.data);s=this.endTaskPerformance(s),this.sendToMainWorker({data:r,taskPerformance:s,workerId:this.id,id:t.id})}catch(e){const s=this.handleError(e);this.sendToMainWorker({taskError:{message:s,data:t.data},workerId:this.id,id:t.id})}finally{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())}}runAsync(e,t){let s=this.beginTaskPerformance();e(t.data).then((e=>(s=this.endTaskPerformance(s),this.sendToMainWorker({data:e,taskPerformance:s,workerId:this.id,id:t.id}),null))).catch((e=>{const s=this.handleError(e);this.sendToMainWorker({taskError:{message:s,data:t.data},workerId:this.id,id:t.id})})).finally((()=>{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())})).catch(d)}getTaskFunction(e){e=e??Q;const t=this.taskFunctions.get(e);if(null==t)throw new Error(`Task function '${e}' not found`);return t}beginTaskPerformance(){return this.checkStatistics(),{timestamp:r.performance.now(),...this.statistics.elu&&{elu:r.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:r.performance.now()-e.timestamp},...this.statistics.elu&&{elu:r.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}}exports.ClusterWorker=class extends _{constructor(e,s={}){super("worker-cluster-pool:poolifier",t.isPrimary,e,t.worker,s)}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}},exports.DynamicClusterPool=class extends P{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends A{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=P,exports.FixedThreadPool=A,exports.KillBehaviors=T,exports.Measurements=y,exports.PoolEvents=c,exports.PoolTypes=h,exports.ThreadWorker=class extends _{constructor(e,t={}){super("worker-thread-pool:poolifier",o.isMainThread,e,o.parentPort,t)}get id(){return o.threadId}sendToMainWorker(e){this.getMainWorker().postMessage(e)}handleError(e){return e}},exports.WorkerChoiceStrategies=f,exports.WorkerTypes=z,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}; | ||
"use strict";var e=require("node:events"),t=require("node:cluster"),s=require("node:crypto"),r=require("node:perf_hooks"),i=require("node:os"),o=require("node:worker_threads"),a=require("node:async_hooks");function n(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=n(i);const h=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class k extends e.EventEmitter{}const c=Object.freeze({full:"full",ready:"ready",busy:"busy",error:"error",taskError:"taskError"}),d="default",m=Object.freeze((()=>{})),l={runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},g={aggregate:!1,average:!1,median:!1},p=e=>{if(Array.isArray(e)&&0===e.length)return 0;if(Array.isArray(e)&&1===e.length)return e[0];const t=e.slice().sort(((e,t)=>e-t));return(t[t.length-1>>1]+t[t.length>>1])/2},w=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},T=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),f=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),y=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"}),W=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class S{pool;opts;nextWorkerNodeId=0;strategyPolicy={useDynamicWorker:!1};taskStatisticsRequirements={runTime:g,waitTime:g,elu:g};constructor(e,t=l){this.pool=e,this.opts=t,this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.taskStatisticsRequirements.runTime.average&&!0===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!1,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.runTime.median&&!1===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!0,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.waitTime.average&&!0===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!1,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.waitTime.median&&!1===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!0,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.elu.average&&!0===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!1,this.taskStatisticsRequirements.elu.median=e.elu.median),this.taskStatisticsRequirements.elu.median&&!1===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!0,this.taskStatisticsRequirements.elu.median=e.elu.median)}setOptions(e){this.opts=e??l,this.setTaskStatisticsRequirements(this.opts)}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 i.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/i.cpus().length)}}class x extends S{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:g,elu:{aggregate:!0,average:!0,median:!1}};workersVirtualTaskEndTimestamp=[];constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.workersVirtualTaskEndTimestamp=[],!0}update(e){return this.computeWorkerVirtualTaskEndTimestamp(e),!0}choose(){let e=1/0;for(const[t]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[t]&&this.computeWorkerVirtualTaskEndTimestamp(t);const s=this.workersVirtualTaskEndTimestamp[t];s<e&&(e=s,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===W.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class N extends S{strategyPolicy={useDynamicWorker:!0};roundId=0;roundWeights;defaultWorkerWeight;constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.nextWorkerNodeId=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.nextWorkerNodeId;r<this.pool.workerNodes.length;r++){if((this.opts.weights?.[r]??this.defaultWorkerWeight)>=this.roundWeights[s]){e=s,t=r;break}}this.roundId=e??0,this.nextWorkerNodeId=t??0;const s=this.nextWorkerNodeId;return this.nextWorkerNodeId===this.pool.workerNodes.length-1?(this.nextWorkerNodeId=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeId=this.nextWorkerNodeId+1,s}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=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 S{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:g};constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===r){this.nextWorkerNodeId=t;break}r<e&&(e=r,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class I extends S{constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class E extends S{taskStatisticsRequirements={runTime:g,waitTime:g,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage,i=r.elu?.active?.aggregate??0;if(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class R extends S{strategyPolicy={useDynamicWorker:!0};constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.nextWorkerNodeId=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId;return this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1)),!0}}class b extends S{strategyPolicy={useDynamicWorker:!0};taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:g,elu:g};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.nextWorkerNodeId=0,this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId,t=this.workerVirtualTaskRunTime;return t<(this.opts.weights?.[e]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=t+this.getWorkerTaskRunTime(e):(this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,this.workerVirtualTaskRunTime=0),e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}}class C{workerChoiceStrategy;workerChoiceStrategies;constructor(e,t=y.ROUND_ROBIN,s=l){this.workerChoiceStrategy=t,this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[y.ROUND_ROBIN,new(R.bind(this))(e,s)],[y.LEAST_USED,new(I.bind(this))(e,s)],[y.LEAST_BUSY,new(v.bind(this))(e,s)],[y.LEAST_ELU,new(E.bind(this))(e,s)],[y.FAIR_SHARE,new(x.bind(this))(e,s)],[y.WEIGHTED_ROUND_ROBIN,new(b.bind(this))(e,s)],[y.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(N.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)throw new Error("Worker node key chosen is null or undefined");return e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class O 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;return arguments.length>=3&&void 0!==t?(r=super.splice(e,t),this.push(...s)):r=2===arguments.length?super.splice(e,t):super.splice(e),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 z{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({cluster:"cluster",thread:"thread"});class M{worker;info;usage;tasksUsage;tasksQueue;constructor(e,t){this.worker=e,this.info=this.initWorkerInfo(e,t),this.usage=this.initWorkerUsage(),this.tasksUsage=new Map,this.tasksQueue=new z}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()}resetUsage(){this.usage=this.initWorkerUsage(),this.tasksUsage.clear()}getTaskWorkerUsage(e){return this.tasksUsage.has(e)||this.tasksUsage.set(e,this.initTaskWorkerUsage(e)),this.tasksUsage.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 O},waitTime:{history:new O},elu:{idle:{history:new O},active:{history:new O}}}}initTaskWorkerUsage(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 O},waitTime:{history:new O},elu:{idle:{history:new O},active:{history:new O}}}}getWorkerId(e,t){return t===q.thread?e.threadId:t===q.cluster?e.id:void 0}}class P{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;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!");for(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),this.checkAndEmitEvents=this.checkAndEmitEvents.bind(this),!0===this.opts.enableEvents&&(this.emitter=new k),this.workerChoiceStrategyContext=new C(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook();this.workerNodes.length<this.numberOfWorkers;)this.createAndSetupWorker();this.startTimestamp=r.performance.now()}checkFilePath(e){if(null==e||"string"==typeof e&&0===e.trim().length)throw new Error("Please specify a file with a worker implementation")}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new 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===h.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkDynamicPoolSize(e,t){if(this.type===h.dynamic){if(e>t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size");if(0===e&&0===t)throw new RangeError("Cannot instantiate a dynamic pool with a minimum pool size and 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(!T(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??y.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions=e.workerChoiceStrategyOptions??l,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(y).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!T(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e.measurement&&!Object.values(W).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(e){if(null!=e&&!T(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new Error(`Invalid worker tasks concurrency '${e.concurrency}'`)}get info(){return{version:"2.6.13",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:w(this.utilization)},workerNodes:this.workerNodes.length,idleWorkerNodes:this.workerNodes.reduce(((e,t)=>0===t.usage.tasks.executing?e+1:e),0),busyWorkerNodes:this.workerNodes.reduce(((e,t)=>t.usage.tasks.executing>0?e+1:e),0),executedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executed),0),executingTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executing),0),queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0),maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.maxQueued??0)),0),failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:w(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:w(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:w(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:w(p(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:w(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:w(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:w(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:w(p(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get starting(){return this.workerNodes.length<this.minSize||this.workerNodes.length>=this.minSize&&this.workerNodes.some((e=>!e.info.ready))}get ready(){return this.workerNodes.length>=this.minSize&&this.workerNodes.every((e=>e.info.ready))}get utilization(){const e=(r.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}getWorkerById(e){return this.workerNodes.find((t=>t.info.id===e))?.worker}checkMessageWorkerId(e){if(null!=e.workerId&&null==this.getWorkerById(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKey(e){return this.workerNodes.findIndex((t=>t.worker===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 of this.workerNodes)e.resetUsage(),this.setWorkerStatistics(e.worker)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions=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-1===this.workerNodes.findIndex((e=>0===e.usage.tasks.executing))}async execute(e,t){const i=r.performance.now(),o=this.chooseWorkerNode(),a={name:t??d,data:e??{},timestamp:i,workerId:this.getWorkerInfo(o).id,id:s.randomUUID()},n=new Promise(((e,t)=>{this.promiseResponseMap.set(a.id,{resolve:e,reject:t,worker:this.workerNodes[o].worker})}));return!0===this.opts.enableTasksQueue&&(this.busy||this.workerNodes[o].usage.tasks.executing>=this.opts.tasksQueueOptions.concurrency)?this.enqueueTask(o,a):this.executeTask(o,a),this.checkAndEmitEvents(),n}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{this.flushTasksQueue(t);const s=new Promise((t=>{e.worker.on("exit",(()=>{t()}))}));await this.destroyWorker(e.worker),await s})))}setupHook(){}beforeTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t);const r=this.workerNodes[e].getTaskWorkerUsage(t.name);++r.tasks.executing,this.updateWaitTimeWorkerUsage(r,t)}afterTaskExecutionHook(e,t){const s=this.getWorkerNodeKey(e),r=this.workerNodes[s].usage;this.updateTaskStatisticsWorkerUsage(r,t),this.updateRunTimeWorkerUsage(r,t),this.updateEluWorkerUsage(r,t);const i=this.workerNodes[s].getTaskWorkerUsage(t.name);this.updateTaskStatisticsWorkerUsage(i,t),this.updateRunTimeWorkerUsage(i,t),this.updateEluWorkerUsage(i,t)}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;--s.executing,null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){if(this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate){const s=t.taskPerformance?.runTime??0;e.runTime.aggregate=(e.runTime.aggregate??0)+s,e.runTime.minimum=Math.min(s,e.runTime?.minimum??1/0),e.runTime.maximum=Math.max(s,e.runTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&0!==e.tasks.executed&&(e.runTime.average=e.runTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&null!=t.taskPerformance?.runTime&&(e.runTime.history.push(t.taskPerformance.runTime),e.runTime.median=p(e.runTime.history))}}updateWaitTimeWorkerUsage(e,t){const s=r.performance.now(),i=s-(t.timestamp??s);this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&(e.waitTime.aggregate=(e.waitTime?.aggregate??0)+i,e.waitTime.minimum=Math.min(i,e.waitTime?.minimum??1/0),e.waitTime.maximum=Math.max(i,e.waitTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&0!==e.tasks.executed&&(e.waitTime.average=e.waitTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&(e.waitTime.history.push(i),e.waitTime.median=p(e.waitTime.history)))}updateEluWorkerUsage(e,t){this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate&&null!=t.taskPerformance?.elu&&(e.elu.idle.aggregate=(e.elu.idle?.aggregate??0)+t.taskPerformance.elu.idle,e.elu.active.aggregate=(e.elu.active?.aggregate??0)+t.taskPerformance.elu.active,null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization,e.elu.idle.minimum=Math.min(t.taskPerformance.elu.idle,e.elu.idle?.minimum??1/0),e.elu.idle.maximum=Math.max(t.taskPerformance.elu.idle,e.elu.idle?.maximum??-1/0),e.elu.active.minimum=Math.min(t.taskPerformance.elu.active,e.elu.active?.minimum??1/0),e.elu.active.maximum=Math.max(t.taskPerformance.elu.active,e.elu.active?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.average&&0!==e.tasks.executed&&(e.elu.idle.average=e.elu.idle.aggregate/e.tasks.executed,e.elu.active.average=e.elu.active.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.median&&(e.elu.idle.history.push(t.taskPerformance.elu.idle),e.elu.active.history.push(t.taskPerformance.elu.active),e.elu.idle.median=p(e.elu.idle.history),e.elu.active.median=p(e.elu.active.history)))}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorker();if(this.workerChoiceStrategyContext.getStrategyPolicy().useDynamicWorker)return this.getWorkerNodeKey(e)}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===h.dynamic&&!this.full&&this.internalBusy()}registerWorkerMessageListener(e,t){e.on("message",t)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,this.workerListener()),this.sendToWorker(e,{ready:!1,workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id}),this.setWorkerStatistics(e)}createAndSetupWorker(){const e=this.createWorker();return e.on("message",this.opts.messageHandler??m),e.on("error",this.opts.errorHandler??m),e.on("error",(t=>{null!=this.emitter&&this.emitter.emit(c.error,t),!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(e),!0!==this.opts.restartWorkerOnError||this.starting||(this.getWorkerInfo(this.getWorkerNodeKey(e)).dynamic?this.createAndSetupDynamicWorker():this.createAndSetupWorker())})),e.on("online",this.opts.onlineHandler??m),e.on("exit",this.opts.exitHandler??m),e.once("exit",(()=>{this.removeWorkerNode(e)})),this.pushWorkerNode(e),this.afterWorkerSetup(e),e}redistributeQueuedTasks(e){const t=this.getWorkerNodeKey(e);for(;this.tasksQueueSize(t)>0;){let e=t,s=1/0;for(const[r,i]of this.workerNodes.entries()){if(r!==t&&0===i.usage.tasks.queued){e=r;break}r!==t&&i.usage.tasks.queued<s&&(s=i.usage.tasks.queued,e=r)}this.enqueueTask(e,this.dequeueTask(t))}}createAndSetupDynamicWorker(){const e=this.createAndSetupWorker();this.registerWorkerMessageListener(e,(t=>{const s=this.getWorkerNodeKey(e);var r;r=f.HARD,(t.kill===r||null!=t.kill&&(!1===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing||!0===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing&&0===this.tasksQueueSize(s)))&&this.destroyWorker(e)}));const t=this.getWorkerInfo(this.getWorkerNodeKey(e));return t.dynamic=!0,this.sendToWorker(e,{checkAlive:!0,workerId:t.id}),e}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.workerId?this.handleWorkerReadyMessage(e):null!=e.id&&this.handleTaskExecutionResponse(e)}}handleWorkerReadyMessage(e){const t=this.getWorkerById(e.workerId);this.getWorkerInfo(this.getWorkerNodeKey(t)).ready=e.ready,null!=this.emitter&&this.ready&&this.emitter.emit(c.ready,this.info)}handleTaskExecutionResponse(e){const t=this.promiseResponseMap.get(e.id);if(null!=t){null!=e.taskError?(null!=this.emitter&&this.emitter.emit(c.taskError,e.taskError),t.reject(e.taskError.message)):t.resolve(e.data),this.afterTaskExecutionHook(t.worker,e),this.promiseResponseMap.delete(e.id);const s=this.getWorkerNodeKey(t.worker);!0===this.opts.enableTasksQueue&&this.tasksQueueSize(s)>0&&this.executeTask(s,this.dequeueTask(s)),this.workerChoiceStrategyContext.update(s)}}checkAndEmitEvents(){null!=this.emitter&&(this.busy&&this.emitter.emit(c.busy,this.info),this.type===h.dynamic&&this.full&&this.emitter.emit(c.full,this.info))}getWorkerInfo(e){return this.workerNodes[e].info}pushWorkerNode(e){return this.workerNodes.push(new M(e,this.worker))}removeWorkerNode(e){const t=this.getWorkerNodeKey(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}executeTask(e,t){this.beforeTaskExecutionHook(e,t),this.sendToWorker(this.workerNodes[e].worker,t)}enqueueTask(e,t){return this.workerNodes[e].enqueueTask(t)}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)}setWorkerStatistics(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id})}}class A extends P{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){t.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return t.isPrimary}destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.id}),e.on("disconnect",(()=>{e.kill()})),e.disconnect()}sendToWorker(e,t){e.send(t)}createWorker(){return t.fork(this.opts.env)}get type(){return h.fixed}get worker(){return q.cluster}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}class Q extends P{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return o.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.threadId}),await e.terminate()}sendToWorker(e,t){e.postMessage(t)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV,...this.opts.workerOptions})}get type(){return h.fixed}get worker(){return q.thread}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}const U=6e4,D=f.SOFT;class F extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;aliveInterval;constructor(e,t,s,r,i={killBehavior:D,maxInactiveTime:U}){super(e),this.isMain=t,this.mainWorker=r,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(s),this.isMain||this.mainWorker?.on("message",this.messageListener.bind(this))}checkWorkerOptions(e){this.opts.killBehavior=e.killBehavior??D,this.opts.maxInactiveTime=e.maxInactiveTime??U,delete this.opts.async}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e)this.taskFunctions.set(d,e.bind(this));else{if(!T(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){if("string"!=typeof s)throw new TypeError("A taskFunctions parameter object key is not a string");if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");this.taskFunctions.set(s,r.bind(this)),t&&(this.taskFunctions.set(d,r.bind(this)),t=!1)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){if("string"!=typeof e)throw new TypeError("name parameter is not a string");return this.taskFunctions.has(e)}addTaskFunction(e,t){if("string"!=typeof e)throw new TypeError("name parameter is not a string");if(e===d)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{return this.taskFunctions.get(e)===this.taskFunctions.get(d)&&this.taskFunctions.set(d,t.bind(this)),this.taskFunctions.set(e,t.bind(this)),!0}catch{return!1}}removeTaskFunction(e){if("string"!=typeof e)throw new TypeError("name parameter is not a string");if(e===d)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(d))throw new Error("Cannot remove the task function used as the default task function");return this.taskFunctions.delete(e)}setDefaultTaskFunction(e){if("string"!=typeof e)throw new TypeError("name parameter is not a string");if(e===d)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(d,this.taskFunctions.get(e)?.bind(this)),!0}catch{return!1}}messageListener(e){e.workerId===this.id&&(null!=e.ready?this.workerReady():null!=e.statistics?this.statistics=e.statistics:null!=e.checkAlive?e.checkAlive?this.startCheckAlive():this.stopCheckAlive():null!=e.id&&null!=e.data?this.run(e):!0===e.kill&&(this.stopCheckAlive(),this.emitDestroy()))}workerReady(){!this.isMain&&this.sendToMainWorker({ready:!0,workerId:this.id})}startCheckAlive(){this.lastTaskTimestamp=r.performance.now(),this.aliveInterval=setInterval(this.checkAlive.bind(this),(this.opts.maxInactiveTime??U)/2),this.checkAlive.bind(this)()}stopCheckAlive(){null!=this.aliveInterval&&clearInterval(this.aliveInterval)}checkAlive(){r.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??U)&&this.sendToMainWorker({kill:this.opts.killBehavior,workerId:this.id})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}handleError(e){return e instanceof Error?e.message:e}run(e){const t=this.getTaskFunction(e.name);(e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name)(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}runSync(e,t){try{let s=this.beginTaskPerformance(t.name);const r=e(t.data);s=this.endTaskPerformance(s),this.sendToMainWorker({data:r,taskPerformance:s,workerId:this.id,id:t.id})}catch(e){const s=this.handleError(e);this.sendToMainWorker({taskError:{name:t.name??d,message:s,data:t.data},workerId:this.id,id:t.id})}finally{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())}}runAsync(e,t){let s=this.beginTaskPerformance(t.name);e(t.data).then((e=>(s=this.endTaskPerformance(s),this.sendToMainWorker({data:e,taskPerformance:s,workerId:this.id,id:t.id}),null))).catch((e=>{const s=this.handleError(e);this.sendToMainWorker({taskError:{name:t.name??d,message:s,data:t.data},workerId:this.id,id:t.id})})).finally((()=>{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())})).catch(m)}getTaskFunction(e){e=e??d;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??d,timestamp:r.performance.now(),...this.statistics.elu&&{elu:r.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:r.performance.now()-e.timestamp},...this.statistics.elu&&{elu:r.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}}exports.ClusterWorker=class extends F{constructor(e,s={}){super("worker-cluster-pool:poolifier",t.isPrimary,e,t.worker,s)}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}},exports.DynamicClusterPool=class extends A{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends Q{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=A,exports.FixedThreadPool=Q,exports.KillBehaviors=f,exports.Measurements=W,exports.PoolEvents=c,exports.PoolTypes=h,exports.ThreadWorker=class extends F{constructor(e,t={}){super("worker-thread-pool:poolifier",o.isMainThread,e,o.parentPort,t)}get id(){return o.threadId}sendToMainWorker(e){this.getMainWorker().postMessage(e)}handleError(e){return e}},exports.WorkerChoiceStrategies=y,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}; |
@@ -7,3 +7,3 @@ export type { AbstractPool } from './pools/abstract-pool'; | ||
export { WorkerTypes } from './pools/worker'; | ||
export type { ErrorHandler, EventLoopUtilizationMeasurementStatistics, ExitHandler, IWorker, IWorkerNode, MeasurementStatistics, MessageHandler, OnlineHandler, Task, TaskStatistics, WorkerInfo, WorkerType, WorkerUsage } from './pools/worker'; | ||
export type { ErrorHandler, EventLoopUtilizationMeasurementStatistics, ExitHandler, IWorker, IWorkerNode, MeasurementStatistics, MessageHandler, OnlineHandler, TaskStatistics, WorkerInfo, WorkerType, WorkerUsage } from './pools/worker'; | ||
export { Measurements, WorkerChoiceStrategies } from './pools/selection-strategies/selection-strategies-types'; | ||
@@ -20,5 +20,5 @@ export type { IWorkerChoiceStrategy, Measurement, MeasurementOptions, MeasurementStatisticsRequirements, StrategyPolicy, TaskStatisticsRequirements, WorkerChoiceStrategy, WorkerChoiceStrategyOptions } from './pools/selection-strategies/selection-strategies-types'; | ||
export type { TaskFunctions, WorkerAsyncFunction, WorkerFunction, WorkerSyncFunction } from './worker/worker-functions'; | ||
export type { MessageValue, PromiseResponseWrapper, TaskError, TaskPerformance, WorkerStatistics } from './utility-types'; | ||
export type { MessageValue, PromiseResponseWrapper, Task, TaskError, TaskPerformance, WorkerStatistics } from './utility-types'; | ||
export type { CircularArray } from './circular-array'; | ||
export type { Queue } from './queue'; | ||
export { availableParallelism } from './utils'; |
@@ -1,1 +0,1 @@ | ||
"use strict";var e=require("node:events"),t=require("node:cluster"),s=require("node:crypto"),r=require("node:perf_hooks"),i=require("node:os"),o=require("node:worker_threads"),a=require("node:async_hooks");function n(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=n(i);const h=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class k extends e.EventEmitter{}const c=Object.freeze({full:"full",ready:"ready",busy:"busy",error:"error",taskError:"taskError"}),d=Object.freeze((()=>{})),m={runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},l={aggregate:!1,average:!1,median:!1},g=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},p=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},w=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),T=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),f=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LEAST_USED:"LEAST_USED",LEAST_BUSY:"LEAST_BUSY",LEAST_ELU:"LEAST_ELU",FAIR_SHARE:"FAIR_SHARE",WEIGHTED_ROUND_ROBIN:"WEIGHTED_ROUND_ROBIN",INTERLEAVED_WEIGHTED_ROUND_ROBIN:"INTERLEAVED_WEIGHTED_ROUND_ROBIN"}),y=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class W{pool;opts;nextWorkerNodeId=0;strategyPolicy={useDynamicWorker:!1};taskStatisticsRequirements={runTime:l,waitTime:l,elu:l};constructor(e,t=m){this.pool=e,this.opts=t,this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.taskStatisticsRequirements.runTime.average&&!0===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!1,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.runTime.median&&!1===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!0,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.waitTime.average&&!0===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!1,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.waitTime.median&&!1===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!0,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.elu.average&&!0===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!1,this.taskStatisticsRequirements.elu.median=e.elu.median),this.taskStatisticsRequirements.elu.median&&!1===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!0,this.taskStatisticsRequirements.elu.median=e.elu.median)}setOptions(e){this.opts=e??m,this.setTaskStatisticsRequirements(this.opts)}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 i.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/i.cpus().length)}}class S extends W{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:l,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(){let e=1/0;for(const[t]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[t]&&this.computeWorkerVirtualTaskEndTimestamp(t);const s=this.workersVirtualTaskEndTimestamp[t];s<e&&(e=s,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===y.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class x extends W{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.nextWorkerNodeId=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.nextWorkerNodeId;r<this.pool.workerNodes.length;r++){if((this.opts.weights?.[r]??this.defaultWorkerWeight)>=this.roundWeights[s]){e=s,t=r;break}}this.roundId=e??0,this.nextWorkerNodeId=t??0;const s=this.nextWorkerNodeId;return this.nextWorkerNodeId===this.pool.workerNodes.length-1?(this.nextWorkerNodeId=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeId=this.nextWorkerNodeId+1,s}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=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 N extends W{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:l};constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===r){this.nextWorkerNodeId=t;break}r<e&&(e=r,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class I extends W{constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class v extends W{taskStatisticsRequirements={runTime:l,waitTime:l,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(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage,i=r.elu?.active?.aggregate??0;if(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class E extends W{strategyPolicy={useDynamicWorker:!0};constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.nextWorkerNodeId=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId;return this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1)),!0}}class R extends W{strategyPolicy={useDynamicWorker:!0};taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:l,elu:l};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=m){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.nextWorkerNodeId=0,this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId,t=this.workerVirtualTaskRunTime;return t<(this.opts.weights?.[e]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=t+this.getWorkerTaskRunTime(e):(this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,this.workerVirtualTaskRunTime=0),e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}}class b{workerChoiceStrategy;workerChoiceStrategies;constructor(e,t=f.ROUND_ROBIN,s=m){this.workerChoiceStrategy=t,this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[f.ROUND_ROBIN,new(E.bind(this))(e,s)],[f.LEAST_USED,new(I.bind(this))(e,s)],[f.LEAST_BUSY,new(N.bind(this))(e,s)],[f.LEAST_ELU,new(v.bind(this))(e,s)],[f.FAIR_SHARE,new(S.bind(this))(e,s)],[f.WEIGHTED_ROUND_ROBIN,new(R.bind(this))(e,s)],[f.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(x.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)throw new Error("Worker node key chosen is null or undefined");return e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class C 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;return arguments.length>=3&&void 0!==t?(r=super.splice(e,t),this.push(...s)):r=2===arguments.length?super.splice(e,t):super.splice(e),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 O{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}}const z=Object.freeze({cluster:"cluster",thread:"thread"});class q{worker;info;usage;tasksQueue;constructor(e,t){this.worker=e,this.info=this.initWorkerInfo(e,t),this.usage=this.initWorkerUsage(),this.tasksQueue=new O}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()}resetUsage(){this.usage=this.initWorkerUsage()}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 C},waitTime:{history:new C},elu:{idle:{history:new C},active:{history:new C}}}}getWorkerId(e,t){return t===z.thread?e.threadId:t===z.cluster?e.id:void 0}}class M{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;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!");for(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),this.checkAndEmitEvents=this.checkAndEmitEvents.bind(this),!0===this.opts.enableEvents&&(this.emitter=new k),this.workerChoiceStrategyContext=new b(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook();this.workerNodes.length<this.numberOfWorkers;)this.createAndSetupWorker();this.startTimestamp=r.performance.now()}checkFilePath(e){if(null==e||"string"==typeof e&&0===e.trim().length)throw new Error("Please specify a file with a worker implementation")}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new 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===h.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkDynamicPoolSize(e,t){if(this.type===h.dynamic){if(e>t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size");if(0===e&&0===t)throw new RangeError("Cannot instantiate a dynamic pool with a minimum pool size and 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(!w(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??f.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions=e.workerChoiceStrategyOptions??m,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(f).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!w(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e.measurement&&!Object.values(y).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(e){if(null!=e&&!w(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new Error(`Invalid worker tasks concurrency '${e.concurrency}'`)}get info(){return{version:"2.6.12",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:p(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),queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0),maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.maxQueued),0),failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:p(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:p(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:p(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:p(g(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:p(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:p(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:p(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:p(g(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get starting(){return this.workerNodes.length<this.minSize||this.workerNodes.length>=this.minSize&&this.workerNodes.some((e=>!e.info.ready))}get ready(){return this.workerNodes.length>=this.minSize&&this.workerNodes.every((e=>e.info.ready))}get utilization(){const e=(r.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}getWorkerById(e){return this.workerNodes.find((t=>t.info.id===e))?.worker}checkMessageWorkerId(e){if(null!=e.workerId&&null==this.getWorkerById(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKey(e){return this.workerNodes.findIndex((t=>t.worker===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 of this.workerNodes)e.resetUsage(),this.setWorkerStatistics(e.worker)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions=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-1===this.workerNodes.findIndex((e=>0===e.usage.tasks.executing))}async execute(e,t){const i=r.performance.now(),o=this.chooseWorkerNode(),a={name:t,data:e??{},timestamp:i,workerId:this.getWorkerInfo(o).id,id:s.randomUUID()},n=new Promise(((e,t)=>{this.promiseResponseMap.set(a.id,{resolve:e,reject:t,worker:this.workerNodes[o].worker})}));return!0===this.opts.enableTasksQueue&&(this.busy||this.workerNodes[o].usage.tasks.executing>=this.opts.tasksQueueOptions.concurrency)?this.enqueueTask(o,a):this.executeTask(o,a),this.checkAndEmitEvents(),n}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{this.flushTasksQueue(t);const s=new Promise((t=>{e.worker.on("exit",(()=>{t()}))}));await this.destroyWorker(e.worker),await s})))}setupHook(){}beforeTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t)}afterTaskExecutionHook(e,t){const s=this.workerNodes[this.getWorkerNodeKey(e)].usage;this.updateTaskStatisticsWorkerUsage(s,t),this.updateRunTimeWorkerUsage(s,t),this.updateEluWorkerUsage(s,t)}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;--s.executing,null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){if(this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate){const s=t.taskPerformance?.runTime??0;e.runTime.aggregate=(e.runTime.aggregate??0)+s,e.runTime.minimum=Math.min(s,e.runTime?.minimum??1/0),e.runTime.maximum=Math.max(s,e.runTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&0!==e.tasks.executed&&(e.runTime.average=e.runTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&null!=t.taskPerformance?.runTime&&(e.runTime.history.push(t.taskPerformance.runTime),e.runTime.median=g(e.runTime.history))}}updateWaitTimeWorkerUsage(e,t){const s=r.performance.now(),i=s-(t.timestamp??s);this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&(e.waitTime.aggregate=(e.waitTime?.aggregate??0)+i,e.waitTime.minimum=Math.min(i,e.waitTime?.minimum??1/0),e.waitTime.maximum=Math.max(i,e.waitTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&0!==e.tasks.executed&&(e.waitTime.average=e.waitTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&(e.waitTime.history.push(i),e.waitTime.median=g(e.waitTime.history)))}updateEluWorkerUsage(e,t){this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate&&null!=t.taskPerformance?.elu&&(e.elu.idle.aggregate=(e.elu.idle?.aggregate??0)+t.taskPerformance.elu.idle,e.elu.active.aggregate=(e.elu.active?.aggregate??0)+t.taskPerformance.elu.active,null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization,e.elu.idle.minimum=Math.min(t.taskPerformance.elu.idle,e.elu.idle?.minimum??1/0),e.elu.idle.maximum=Math.max(t.taskPerformance.elu.idle,e.elu.idle?.maximum??-1/0),e.elu.active.minimum=Math.min(t.taskPerformance.elu.active,e.elu.active?.minimum??1/0),e.elu.active.maximum=Math.max(t.taskPerformance.elu.active,e.elu.active?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.average&&0!==e.tasks.executed&&(e.elu.idle.average=e.elu.idle.aggregate/e.tasks.executed,e.elu.active.average=e.elu.active.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.median&&(e.elu.idle.history.push(t.taskPerformance.elu.idle),e.elu.active.history.push(t.taskPerformance.elu.active),e.elu.idle.median=g(e.elu.idle.history),e.elu.active.median=g(e.elu.active.history)))}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorker();if(this.workerChoiceStrategyContext.getStrategyPolicy().useDynamicWorker)return this.getWorkerNodeKey(e)}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===h.dynamic&&!this.full&&this.internalBusy()}registerWorkerMessageListener(e,t){e.on("message",t)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,this.workerListener()),this.sendToWorker(e,{ready:!1,workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id}),this.setWorkerStatistics(e)}createAndSetupWorker(){const e=this.createWorker();return e.on("message",this.opts.messageHandler??d),e.on("error",this.opts.errorHandler??d),e.on("error",(t=>{null!=this.emitter&&this.emitter.emit(c.error,t),!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(e),!0!==this.opts.restartWorkerOnError||this.starting||(this.getWorkerInfo(this.getWorkerNodeKey(e)).dynamic?this.createAndSetupDynamicWorker():this.createAndSetupWorker())})),e.on("online",this.opts.onlineHandler??d),e.on("exit",this.opts.exitHandler??d),e.once("exit",(()=>{this.removeWorkerNode(e)})),this.pushWorkerNode(e),this.afterWorkerSetup(e),e}redistributeQueuedTasks(e){const t=this.getWorkerNodeKey(e);for(;this.tasksQueueSize(t)>0;){let e=t,s=1/0;for(const[r,i]of this.workerNodes.entries()){if(r!==t&&0===i.usage.tasks.queued){e=r;break}r!==t&&i.usage.tasks.queued<s&&(s=i.usage.tasks.queued,e=r)}this.enqueueTask(e,this.dequeueTask(t))}}createAndSetupDynamicWorker(){const e=this.createAndSetupWorker();this.registerWorkerMessageListener(e,(t=>{const s=this.getWorkerNodeKey(e);var r;r=T.HARD,(t.kill===r||null!=t.kill&&(!1===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing||!0===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing&&0===this.tasksQueueSize(s)))&&this.destroyWorker(e)}));const t=this.getWorkerInfo(this.getWorkerNodeKey(e));return t.dynamic=!0,this.sendToWorker(e,{checkAlive:!0,workerId:t.id}),e}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.workerId?this.handleWorkerReadyMessage(e):null!=e.id&&this.handleTaskExecutionResponse(e)}}handleWorkerReadyMessage(e){const t=this.getWorkerById(e.workerId);this.getWorkerInfo(this.getWorkerNodeKey(t)).ready=e.ready,null!=this.emitter&&this.ready&&this.emitter.emit(c.ready,this.info)}handleTaskExecutionResponse(e){const t=this.promiseResponseMap.get(e.id);if(null!=t){null!=e.taskError?(null!=this.emitter&&this.emitter.emit(c.taskError,e.taskError),t.reject(e.taskError.message)):t.resolve(e.data),this.afterTaskExecutionHook(t.worker,e),this.promiseResponseMap.delete(e.id);const s=this.getWorkerNodeKey(t.worker);!0===this.opts.enableTasksQueue&&this.tasksQueueSize(s)>0&&this.executeTask(s,this.dequeueTask(s)),this.workerChoiceStrategyContext.update(s)}}checkAndEmitEvents(){null!=this.emitter&&(this.busy&&this.emitter.emit(c.busy,this.info),this.type===h.dynamic&&this.full&&this.emitter.emit(c.full,this.info))}getWorkerInfo(e){return this.workerNodes[e].info}pushWorkerNode(e){return this.workerNodes.push(new q(e,this.worker))}removeWorkerNode(e){const t=this.getWorkerNodeKey(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}executeTask(e,t){this.beforeTaskExecutionHook(e,t),this.sendToWorker(this.workerNodes[e].worker,t)}enqueueTask(e,t){return this.workerNodes[e].enqueueTask(t)}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)}setWorkerStatistics(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id})}}class P extends M{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){t.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return t.isPrimary}destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.id}),e.on("disconnect",(()=>{e.kill()})),e.disconnect()}sendToWorker(e,t){e.send(t)}createWorker(){return t.fork(this.opts.env)}get type(){return h.fixed}get worker(){return z.cluster}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}class A extends M{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return o.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.threadId}),await e.terminate()}sendToWorker(e,t){e.postMessage(t)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV,...this.opts.workerOptions})}get type(){return h.fixed}get worker(){return z.thread}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}const Q="default",D=6e4,U=T.SOFT;class _ extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;aliveInterval;constructor(e,t,s,r,i={killBehavior:U,maxInactiveTime:D}){super(e),this.isMain=t,this.mainWorker=r,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(s),this.isMain||this.mainWorker?.on("message",this.messageListener.bind(this))}checkWorkerOptions(e){this.opts.killBehavior=e.killBehavior??U,this.opts.maxInactiveTime=e.maxInactiveTime??D,delete this.opts.async}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e)this.taskFunctions.set(Q,e.bind(this));else{if(!w(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");this.taskFunctions.set(s,r.bind(this)),t&&(this.taskFunctions.set(Q,r.bind(this)),t=!1)}if(t)throw new Error("taskFunctions parameter object is empty")}}}messageListener(e){if(null!=e.ready&&e.workerId===this.id)this.workerReady();else if(null!=e.statistics&&e.workerId===this.id)this.statistics=e.statistics;else if(null!=e.checkAlive&&e.workerId===this.id)e.checkAlive?this.startCheckAlive():this.stopCheckAlive();else if(null!=e.id&&null!=e.data&&e.workerId===this.id){const t=this.getTaskFunction(e.name);(e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name)(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}else!0===e.kill&&e.workerId===this.id&&(this.stopCheckAlive(),this.emitDestroy())}workerReady(){!this.isMain&&this.sendToMainWorker({ready:!0,workerId:this.id})}startCheckAlive(){this.lastTaskTimestamp=r.performance.now(),this.aliveInterval=setInterval(this.checkAlive.bind(this),(this.opts.maxInactiveTime??D)/2),this.checkAlive.bind(this)()}stopCheckAlive(){null!=this.aliveInterval&&clearInterval(this.aliveInterval)}checkAlive(){r.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}handleError(e){return e instanceof Error?e.message:e}runSync(e,t){try{let s=this.beginTaskPerformance();const r=e(t.data);s=this.endTaskPerformance(s),this.sendToMainWorker({data:r,taskPerformance:s,workerId:this.id,id:t.id})}catch(e){const s=this.handleError(e);this.sendToMainWorker({taskError:{message:s,data:t.data},workerId:this.id,id:t.id})}finally{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())}}runAsync(e,t){let s=this.beginTaskPerformance();e(t.data).then((e=>(s=this.endTaskPerformance(s),this.sendToMainWorker({data:e,taskPerformance:s,workerId:this.id,id:t.id}),null))).catch((e=>{const s=this.handleError(e);this.sendToMainWorker({taskError:{message:s,data:t.data},workerId:this.id,id:t.id})})).finally((()=>{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())})).catch(d)}getTaskFunction(e){e=e??Q;const t=this.taskFunctions.get(e);if(null==t)throw new Error(`Task function '${e}' not found`);return t}beginTaskPerformance(){return this.checkStatistics(),{timestamp:r.performance.now(),...this.statistics.elu&&{elu:r.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:r.performance.now()-e.timestamp},...this.statistics.elu&&{elu:r.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}}exports.ClusterWorker=class extends _{constructor(e,s={}){super("worker-cluster-pool:poolifier",t.isPrimary,e,t.worker,s)}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}},exports.DynamicClusterPool=class extends P{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends A{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=P,exports.FixedThreadPool=A,exports.KillBehaviors=T,exports.Measurements=y,exports.PoolEvents=c,exports.PoolTypes=h,exports.ThreadWorker=class extends _{constructor(e,t={}){super("worker-thread-pool:poolifier",o.isMainThread,e,o.parentPort,t)}get id(){return o.threadId}sendToMainWorker(e){this.getMainWorker().postMessage(e)}handleError(e){return e}},exports.WorkerChoiceStrategies=f,exports.WorkerTypes=z,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}; | ||
"use strict";var e=require("node:events"),t=require("node:cluster"),s=require("node:crypto"),r=require("node:perf_hooks"),i=require("node:os"),o=require("node:worker_threads"),a=require("node:async_hooks");function n(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=n(i);const h=Object.freeze({fixed:"fixed",dynamic:"dynamic"});class k extends e.EventEmitter{}const c=Object.freeze({full:"full",ready:"ready",busy:"busy",error:"error",taskError:"taskError"}),d="default",m=Object.freeze((()=>{})),l={runTime:{median:!1},waitTime:{median:!1},elu:{median:!1}},g={aggregate:!1,average:!1,median:!1},p=e=>{if(Array.isArray(e)&&0===e.length)return 0;if(Array.isArray(e)&&1===e.length)return e[0];const t=e.slice().sort(((e,t)=>e-t));return(t[t.length-1>>1]+t[t.length>>1])/2},w=(e,t=2)=>{const s=Math.pow(10,t);return Math.round(e*s*(1+Number.EPSILON))/s},T=e=>"object"==typeof e&&null!==e&&e?.constructor===Object&&"[object Object]"===Object.prototype.toString.call(e),f=Object.freeze({SOFT:"SOFT",HARD:"HARD"}),y=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"}),W=Object.freeze({runTime:"runTime",waitTime:"waitTime",elu:"elu"});class S{pool;opts;nextWorkerNodeId=0;strategyPolicy={useDynamicWorker:!1};taskStatisticsRequirements={runTime:g,waitTime:g,elu:g};constructor(e,t=l){this.pool=e,this.opts=t,this.choose=this.choose.bind(this)}setTaskStatisticsRequirements(e){this.taskStatisticsRequirements.runTime.average&&!0===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!1,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.runTime.median&&!1===e.runTime?.median&&(this.taskStatisticsRequirements.runTime.average=!0,this.taskStatisticsRequirements.runTime.median=e.runTime.median),this.taskStatisticsRequirements.waitTime.average&&!0===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!1,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.waitTime.median&&!1===e.waitTime?.median&&(this.taskStatisticsRequirements.waitTime.average=!0,this.taskStatisticsRequirements.waitTime.median=e.waitTime.median),this.taskStatisticsRequirements.elu.average&&!0===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!1,this.taskStatisticsRequirements.elu.median=e.elu.median),this.taskStatisticsRequirements.elu.median&&!1===e.elu?.median&&(this.taskStatisticsRequirements.elu.average=!0,this.taskStatisticsRequirements.elu.median=e.elu.median)}setOptions(e){this.opts=e??l,this.setTaskStatisticsRequirements(this.opts)}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 i.cpus()){const s=t.speed.toString().length-1;e+=1/(t.speed/Math.pow(10,s))*Math.pow(10,s)}return Math.round(e/i.cpus().length)}}class x extends S{taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:g,elu:{aggregate:!0,average:!0,median:!1}};workersVirtualTaskEndTimestamp=[];constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.workersVirtualTaskEndTimestamp=[],!0}update(e){return this.computeWorkerVirtualTaskEndTimestamp(e),!0}choose(){let e=1/0;for(const[t]of this.pool.workerNodes.entries()){null==this.workersVirtualTaskEndTimestamp[t]&&this.computeWorkerVirtualTaskEndTimestamp(t);const s=this.workersVirtualTaskEndTimestamp[t];s<e&&(e=s,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(e){return this.workersVirtualTaskEndTimestamp.splice(e,1),!0}computeWorkerVirtualTaskEndTimestamp(e){this.workersVirtualTaskEndTimestamp[e]=this.getWorkerVirtualTaskEndTimestamp(e,this.getWorkerVirtualTaskStartTimestamp(e))}getWorkerVirtualTaskEndTimestamp(e,t){return t+(this.opts.measurement===W.elu?this.getWorkerTaskElu(e):this.getWorkerTaskRunTime(e))}getWorkerVirtualTaskStartTimestamp(e){return Math.max(performance.now(),this.workersVirtualTaskEndTimestamp[e]??-1/0)}}class N extends S{strategyPolicy={useDynamicWorker:!0};roundId=0;roundWeights;defaultWorkerWeight;constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight(),this.roundWeights=this.getRoundWeights()}reset(){return this.nextWorkerNodeId=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.nextWorkerNodeId;r<this.pool.workerNodes.length;r++){if((this.opts.weights?.[r]??this.defaultWorkerWeight)>=this.roundWeights[s]){e=s,t=r;break}}this.roundId=e??0,this.nextWorkerNodeId=t??0;const s=this.nextWorkerNodeId;return this.nextWorkerNodeId===this.pool.workerNodes.length-1?(this.nextWorkerNodeId=0,this.roundId=this.roundId===this.roundWeights.length-1?0:this.roundId+1):this.nextWorkerNodeId=this.nextWorkerNodeId+1,s}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=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 S{taskStatisticsRequirements={runTime:{aggregate:!0,average:!1,median:!1},waitTime:{aggregate:!0,average:!1,median:!1},elu:g};constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===r){this.nextWorkerNodeId=t;break}r<e&&(e=r,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class I extends S{constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){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(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class E extends S{taskStatisticsRequirements={runTime:g,waitTime:g,elu:{aggregate:!0,average:!1,median:!1}};constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return!0}update(){return!0}choose(){let e=1/0;for(const[t,s]of this.pool.workerNodes.entries()){const r=s.usage,i=r.elu?.active?.aggregate??0;if(0===i){this.nextWorkerNodeId=t;break}i<e&&(e=i,this.nextWorkerNodeId=t)}return this.nextWorkerNodeId}remove(){return!0}}class R extends S{strategyPolicy={useDynamicWorker:!0};constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts)}reset(){return this.nextWorkerNodeId=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId;return this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1)),!0}}class b extends S{strategyPolicy={useDynamicWorker:!0};taskStatisticsRequirements={runTime:{aggregate:!0,average:!0,median:!1},waitTime:g,elu:g};defaultWorkerWeight;workerVirtualTaskRunTime=0;constructor(e,t=l){super(e,t),this.setTaskStatisticsRequirements(this.opts),this.defaultWorkerWeight=this.computeDefaultWorkerWeight()}reset(){return this.nextWorkerNodeId=0,this.workerVirtualTaskRunTime=0,!0}update(){return!0}choose(){const e=this.nextWorkerNodeId,t=this.workerVirtualTaskRunTime;return t<(this.opts.weights?.[e]??this.defaultWorkerWeight)?this.workerVirtualTaskRunTime=t+this.getWorkerTaskRunTime(e):(this.nextWorkerNodeId=this.nextWorkerNodeId===this.pool.workerNodes.length-1?0:this.nextWorkerNodeId+1,this.workerVirtualTaskRunTime=0),e}remove(e){return this.nextWorkerNodeId===e&&(0===this.pool.workerNodes.length?this.nextWorkerNodeId=0:this.nextWorkerNodeId>this.pool.workerNodes.length-1&&(this.nextWorkerNodeId=this.pool.workerNodes.length-1),this.workerVirtualTaskRunTime=0),!0}}class C{workerChoiceStrategy;workerChoiceStrategies;constructor(e,t=y.ROUND_ROBIN,s=l){this.workerChoiceStrategy=t,this.execute=this.execute.bind(this),this.workerChoiceStrategies=new Map([[y.ROUND_ROBIN,new(R.bind(this))(e,s)],[y.LEAST_USED,new(I.bind(this))(e,s)],[y.LEAST_BUSY,new(v.bind(this))(e,s)],[y.LEAST_ELU,new(E.bind(this))(e,s)],[y.FAIR_SHARE,new(x.bind(this))(e,s)],[y.WEIGHTED_ROUND_ROBIN,new(b.bind(this))(e,s)],[y.INTERLEAVED_WEIGHTED_ROUND_ROBIN,new(N.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)throw new Error("Worker node key chosen is null or undefined");return e}remove(e){return this.workerChoiceStrategies.get(this.workerChoiceStrategy).remove(e)}setOptions(e){for(const t of this.workerChoiceStrategies.values())t.setOptions(e)}}class O 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;return arguments.length>=3&&void 0!==t?(r=super.splice(e,t),this.push(...s)):r=2===arguments.length?super.splice(e,t):super.splice(e),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 z{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({cluster:"cluster",thread:"thread"});class M{worker;info;usage;tasksUsage;tasksQueue;constructor(e,t){this.worker=e,this.info=this.initWorkerInfo(e,t),this.usage=this.initWorkerUsage(),this.tasksUsage=new Map,this.tasksQueue=new z}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()}resetUsage(){this.usage=this.initWorkerUsage(),this.tasksUsage.clear()}getTaskWorkerUsage(e){return this.tasksUsage.has(e)||this.tasksUsage.set(e,this.initTaskWorkerUsage(e)),this.tasksUsage.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 O},waitTime:{history:new O},elu:{idle:{history:new O},active:{history:new O}}}}initTaskWorkerUsage(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 O},waitTime:{history:new O},elu:{idle:{history:new O},active:{history:new O}}}}getWorkerId(e,t){return t===q.thread?e.threadId:t===q.cluster?e.id:void 0}}class P{numberOfWorkers;filePath;opts;workerNodes=[];emitter;promiseResponseMap=new Map;workerChoiceStrategyContext;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!");for(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),this.checkAndEmitEvents=this.checkAndEmitEvents.bind(this),!0===this.opts.enableEvents&&(this.emitter=new k),this.workerChoiceStrategyContext=new C(this,this.opts.workerChoiceStrategy,this.opts.workerChoiceStrategyOptions),this.setupHook();this.workerNodes.length<this.numberOfWorkers;)this.createAndSetupWorker();this.startTimestamp=r.performance.now()}checkFilePath(e){if(null==e||"string"==typeof e&&0===e.trim().length)throw new Error("Please specify a file with a worker implementation")}checkNumberOfWorkers(e){if(null==e)throw new Error("Cannot instantiate a pool without specifying the number of workers");if(!Number.isSafeInteger(e))throw new 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===h.fixed&&0===e)throw new RangeError("Cannot instantiate a fixed pool with zero worker")}checkDynamicPoolSize(e,t){if(this.type===h.dynamic){if(e>t)throw new RangeError("Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size");if(0===e&&0===t)throw new RangeError("Cannot instantiate a dynamic pool with a minimum pool size and 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(!T(e))throw new TypeError("Invalid pool options: must be a plain object");this.opts.workerChoiceStrategy=e.workerChoiceStrategy??y.ROUND_ROBIN,this.checkValidWorkerChoiceStrategy(this.opts.workerChoiceStrategy),this.opts.workerChoiceStrategyOptions=e.workerChoiceStrategyOptions??l,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(y).includes(e))throw new Error(`Invalid worker choice strategy '${e}'`)}checkValidWorkerChoiceStrategyOptions(e){if(!T(e))throw new TypeError("Invalid worker choice strategy options: must be a plain object");if(null!=e.weights&&Object.keys(e.weights).length!==this.maxSize)throw new Error("Invalid worker choice strategy options: must have a weight for each worker node");if(null!=e.measurement&&!Object.values(W).includes(e.measurement))throw new Error(`Invalid worker choice strategy options: invalid measurement '${e.measurement}'`)}checkValidTasksQueueOptions(e){if(null!=e&&!T(e))throw new TypeError("Invalid tasks queue options: must be a plain object");if(null!=e?.concurrency&&!Number.isSafeInteger(e.concurrency))throw new TypeError("Invalid worker tasks concurrency: must be an integer");if(null!=e?.concurrency&&e.concurrency<=0)throw new Error(`Invalid worker tasks concurrency '${e.concurrency}'`)}get info(){return{version:"2.6.13",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:w(this.utilization)},workerNodes:this.workerNodes.length,idleWorkerNodes:this.workerNodes.reduce(((e,t)=>0===t.usage.tasks.executing?e+1:e),0),busyWorkerNodes:this.workerNodes.reduce(((e,t)=>t.usage.tasks.executing>0?e+1:e),0),executedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executed),0),executingTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.executing),0),queuedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.queued),0),maxQueuedTasks:this.workerNodes.reduce(((e,t)=>e+(t.usage.tasks?.maxQueued??0)),0),failedTasks:this.workerNodes.reduce(((e,t)=>e+t.usage.tasks.failed),0),...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate&&{runTime:{minimum:w(Math.min(...this.workerNodes.map((e=>e.usage.runTime?.minimum??1/0)))),maximum:w(Math.max(...this.workerNodes.map((e=>e.usage.runTime?.maximum??-1/0)))),average:w(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:w(p(this.workerNodes.map((e=>e.usage.runTime?.median??0))))}}},...this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&{waitTime:{minimum:w(Math.min(...this.workerNodes.map((e=>e.usage.waitTime?.minimum??1/0)))),maximum:w(Math.max(...this.workerNodes.map((e=>e.usage.waitTime?.maximum??-1/0)))),average:w(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:w(p(this.workerNodes.map((e=>e.usage.waitTime?.median??0))))}}}}}get starting(){return this.workerNodes.length<this.minSize||this.workerNodes.length>=this.minSize&&this.workerNodes.some((e=>!e.info.ready))}get ready(){return this.workerNodes.length>=this.minSize&&this.workerNodes.every((e=>e.info.ready))}get utilization(){const e=(r.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}getWorkerById(e){return this.workerNodes.find((t=>t.info.id===e))?.worker}checkMessageWorkerId(e){if(null!=e.workerId&&null==this.getWorkerById(e.workerId))throw new Error(`Worker message received from unknown worker '${e.workerId}'`)}getWorkerNodeKey(e){return this.workerNodes.findIndex((t=>t.worker===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 of this.workerNodes)e.resetUsage(),this.setWorkerStatistics(e.worker)}setWorkerChoiceStrategyOptions(e){this.checkValidWorkerChoiceStrategyOptions(e),this.opts.workerChoiceStrategyOptions=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-1===this.workerNodes.findIndex((e=>0===e.usage.tasks.executing))}async execute(e,t){const i=r.performance.now(),o=this.chooseWorkerNode(),a={name:t??d,data:e??{},timestamp:i,workerId:this.getWorkerInfo(o).id,id:s.randomUUID()},n=new Promise(((e,t)=>{this.promiseResponseMap.set(a.id,{resolve:e,reject:t,worker:this.workerNodes[o].worker})}));return!0===this.opts.enableTasksQueue&&(this.busy||this.workerNodes[o].usage.tasks.executing>=this.opts.tasksQueueOptions.concurrency)?this.enqueueTask(o,a):this.executeTask(o,a),this.checkAndEmitEvents(),n}async destroy(){await Promise.all(this.workerNodes.map((async(e,t)=>{this.flushTasksQueue(t);const s=new Promise((t=>{e.worker.on("exit",(()=>{t()}))}));await this.destroyWorker(e.worker),await s})))}setupHook(){}beforeTaskExecutionHook(e,t){const s=this.workerNodes[e].usage;++s.tasks.executing,this.updateWaitTimeWorkerUsage(s,t);const r=this.workerNodes[e].getTaskWorkerUsage(t.name);++r.tasks.executing,this.updateWaitTimeWorkerUsage(r,t)}afterTaskExecutionHook(e,t){const s=this.getWorkerNodeKey(e),r=this.workerNodes[s].usage;this.updateTaskStatisticsWorkerUsage(r,t),this.updateRunTimeWorkerUsage(r,t),this.updateEluWorkerUsage(r,t);const i=this.workerNodes[s].getTaskWorkerUsage(t.name);this.updateTaskStatisticsWorkerUsage(i,t),this.updateRunTimeWorkerUsage(i,t),this.updateEluWorkerUsage(i,t)}updateTaskStatisticsWorkerUsage(e,t){const s=e.tasks;--s.executing,null==t.taskError?++s.executed:++s.failed}updateRunTimeWorkerUsage(e,t){if(this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate){const s=t.taskPerformance?.runTime??0;e.runTime.aggregate=(e.runTime.aggregate??0)+s,e.runTime.minimum=Math.min(s,e.runTime?.minimum??1/0),e.runTime.maximum=Math.max(s,e.runTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.average&&0!==e.tasks.executed&&(e.runTime.average=e.runTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.median&&null!=t.taskPerformance?.runTime&&(e.runTime.history.push(t.taskPerformance.runTime),e.runTime.median=p(e.runTime.history))}}updateWaitTimeWorkerUsage(e,t){const s=r.performance.now(),i=s-(t.timestamp??s);this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.aggregate&&(e.waitTime.aggregate=(e.waitTime?.aggregate??0)+i,e.waitTime.minimum=Math.min(i,e.waitTime?.minimum??1/0),e.waitTime.maximum=Math.max(i,e.waitTime?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.average&&0!==e.tasks.executed&&(e.waitTime.average=e.waitTime.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().waitTime.median&&(e.waitTime.history.push(i),e.waitTime.median=p(e.waitTime.history)))}updateEluWorkerUsage(e,t){this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate&&null!=t.taskPerformance?.elu&&(e.elu.idle.aggregate=(e.elu.idle?.aggregate??0)+t.taskPerformance.elu.idle,e.elu.active.aggregate=(e.elu.active?.aggregate??0)+t.taskPerformance.elu.active,null!=e.elu.utilization?e.elu.utilization=(e.elu.utilization+t.taskPerformance.elu.utilization)/2:e.elu.utilization=t.taskPerformance.elu.utilization,e.elu.idle.minimum=Math.min(t.taskPerformance.elu.idle,e.elu.idle?.minimum??1/0),e.elu.idle.maximum=Math.max(t.taskPerformance.elu.idle,e.elu.idle?.maximum??-1/0),e.elu.active.minimum=Math.min(t.taskPerformance.elu.active,e.elu.active?.minimum??1/0),e.elu.active.maximum=Math.max(t.taskPerformance.elu.active,e.elu.active?.maximum??-1/0),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.average&&0!==e.tasks.executed&&(e.elu.idle.average=e.elu.idle.aggregate/e.tasks.executed,e.elu.active.average=e.elu.active.aggregate/e.tasks.executed),this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.median&&(e.elu.idle.history.push(t.taskPerformance.elu.idle),e.elu.active.history.push(t.taskPerformance.elu.active),e.elu.idle.median=p(e.elu.idle.history),e.elu.active.median=p(e.elu.active.history)))}chooseWorkerNode(){if(this.shallCreateDynamicWorker()){const e=this.createAndSetupDynamicWorker();if(this.workerChoiceStrategyContext.getStrategyPolicy().useDynamicWorker)return this.getWorkerNodeKey(e)}return this.workerChoiceStrategyContext.execute()}shallCreateDynamicWorker(){return this.type===h.dynamic&&!this.full&&this.internalBusy()}registerWorkerMessageListener(e,t){e.on("message",t)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,this.workerListener()),this.sendToWorker(e,{ready:!1,workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id}),this.setWorkerStatistics(e)}createAndSetupWorker(){const e=this.createWorker();return e.on("message",this.opts.messageHandler??m),e.on("error",this.opts.errorHandler??m),e.on("error",(t=>{null!=this.emitter&&this.emitter.emit(c.error,t),!0===this.opts.enableTasksQueue&&this.redistributeQueuedTasks(e),!0!==this.opts.restartWorkerOnError||this.starting||(this.getWorkerInfo(this.getWorkerNodeKey(e)).dynamic?this.createAndSetupDynamicWorker():this.createAndSetupWorker())})),e.on("online",this.opts.onlineHandler??m),e.on("exit",this.opts.exitHandler??m),e.once("exit",(()=>{this.removeWorkerNode(e)})),this.pushWorkerNode(e),this.afterWorkerSetup(e),e}redistributeQueuedTasks(e){const t=this.getWorkerNodeKey(e);for(;this.tasksQueueSize(t)>0;){let e=t,s=1/0;for(const[r,i]of this.workerNodes.entries()){if(r!==t&&0===i.usage.tasks.queued){e=r;break}r!==t&&i.usage.tasks.queued<s&&(s=i.usage.tasks.queued,e=r)}this.enqueueTask(e,this.dequeueTask(t))}}createAndSetupDynamicWorker(){const e=this.createAndSetupWorker();this.registerWorkerMessageListener(e,(t=>{const s=this.getWorkerNodeKey(e);var r;r=f.HARD,(t.kill===r||null!=t.kill&&(!1===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing||!0===this.opts.enableTasksQueue&&0===this.workerNodes[s].usage.tasks.executing&&0===this.tasksQueueSize(s)))&&this.destroyWorker(e)}));const t=this.getWorkerInfo(this.getWorkerNodeKey(e));return t.dynamic=!0,this.sendToWorker(e,{checkAlive:!0,workerId:t.id}),e}workerListener(){return e=>{this.checkMessageWorkerId(e),null!=e.ready&&null!=e.workerId?this.handleWorkerReadyMessage(e):null!=e.id&&this.handleTaskExecutionResponse(e)}}handleWorkerReadyMessage(e){const t=this.getWorkerById(e.workerId);this.getWorkerInfo(this.getWorkerNodeKey(t)).ready=e.ready,null!=this.emitter&&this.ready&&this.emitter.emit(c.ready,this.info)}handleTaskExecutionResponse(e){const t=this.promiseResponseMap.get(e.id);if(null!=t){null!=e.taskError?(null!=this.emitter&&this.emitter.emit(c.taskError,e.taskError),t.reject(e.taskError.message)):t.resolve(e.data),this.afterTaskExecutionHook(t.worker,e),this.promiseResponseMap.delete(e.id);const s=this.getWorkerNodeKey(t.worker);!0===this.opts.enableTasksQueue&&this.tasksQueueSize(s)>0&&this.executeTask(s,this.dequeueTask(s)),this.workerChoiceStrategyContext.update(s)}}checkAndEmitEvents(){null!=this.emitter&&(this.busy&&this.emitter.emit(c.busy,this.info),this.type===h.dynamic&&this.full&&this.emitter.emit(c.full,this.info))}getWorkerInfo(e){return this.workerNodes[e].info}pushWorkerNode(e){return this.workerNodes.push(new M(e,this.worker))}removeWorkerNode(e){const t=this.getWorkerNodeKey(e);-1!==t&&(this.workerNodes.splice(t,1),this.workerChoiceStrategyContext.remove(t))}executeTask(e,t){this.beforeTaskExecutionHook(e,t),this.sendToWorker(this.workerNodes[e].worker,t)}enqueueTask(e,t){return this.workerNodes[e].enqueueTask(t)}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)}setWorkerStatistics(e){this.sendToWorker(e,{statistics:{runTime:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().runTime.aggregate,elu:this.workerChoiceStrategyContext.getTaskStatisticsRequirements().elu.aggregate},workerId:this.getWorkerInfo(this.getWorkerNodeKey(e)).id})}}class A extends P{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}setupHook(){t.setupPrimary({...this.opts.settings,exec:this.filePath})}isMain(){return t.isPrimary}destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.id}),e.on("disconnect",(()=>{e.kill()})),e.disconnect()}sendToWorker(e,t){e.send(t)}createWorker(){return t.fork(this.opts.env)}get type(){return h.fixed}get worker(){return q.cluster}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}class Q extends P{opts;constructor(e,t,s={}){super(e,t,s),this.opts=s}isMain(){return o.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:!0,workerId:e.threadId}),await e.terminate()}sendToWorker(e,t){e.postMessage(t)}createWorker(){return new o.Worker(this.filePath,{env:o.SHARE_ENV,...this.opts.workerOptions})}get type(){return h.fixed}get worker(){return q.thread}get minSize(){return this.numberOfWorkers}get maxSize(){return this.numberOfWorkers}get busy(){return this.internalBusy()}}const U=6e4,D=f.SOFT;class F extends a.AsyncResource{isMain;mainWorker;opts;taskFunctions;lastTaskTimestamp;statistics;aliveInterval;constructor(e,t,s,r,i={killBehavior:D,maxInactiveTime:U}){super(e),this.isMain=t,this.mainWorker=r,this.opts=i,this.checkWorkerOptions(this.opts),this.checkTaskFunctions(s),this.isMain||this.mainWorker?.on("message",this.messageListener.bind(this))}checkWorkerOptions(e){this.opts.killBehavior=e.killBehavior??D,this.opts.maxInactiveTime=e.maxInactiveTime??U,delete this.opts.async}checkTaskFunctions(e){if(null==e)throw new Error("taskFunctions parameter is mandatory");if(this.taskFunctions=new Map,"function"==typeof e)this.taskFunctions.set(d,e.bind(this));else{if(!T(e))throw new TypeError("taskFunctions parameter is not a function or a plain object");{let t=!0;for(const[s,r]of Object.entries(e)){if("string"!=typeof s)throw new TypeError("A taskFunctions parameter object key is not a string");if("function"!=typeof r)throw new TypeError("A taskFunctions parameter object value is not a function");this.taskFunctions.set(s,r.bind(this)),t&&(this.taskFunctions.set(d,r.bind(this)),t=!1)}if(t)throw new Error("taskFunctions parameter object is empty")}}}hasTaskFunction(e){if("string"!=typeof e)throw new TypeError("name parameter is not a string");return this.taskFunctions.has(e)}addTaskFunction(e,t){if("string"!=typeof e)throw new TypeError("name parameter is not a string");if(e===d)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{return this.taskFunctions.get(e)===this.taskFunctions.get(d)&&this.taskFunctions.set(d,t.bind(this)),this.taskFunctions.set(e,t.bind(this)),!0}catch{return!1}}removeTaskFunction(e){if("string"!=typeof e)throw new TypeError("name parameter is not a string");if(e===d)throw new Error("Cannot remove the task function with the default reserved name");if(this.taskFunctions.get(e)===this.taskFunctions.get(d))throw new Error("Cannot remove the task function used as the default task function");return this.taskFunctions.delete(e)}setDefaultTaskFunction(e){if("string"!=typeof e)throw new TypeError("name parameter is not a string");if(e===d)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(d,this.taskFunctions.get(e)?.bind(this)),!0}catch{return!1}}messageListener(e){e.workerId===this.id&&(null!=e.ready?this.workerReady():null!=e.statistics?this.statistics=e.statistics:null!=e.checkAlive?e.checkAlive?this.startCheckAlive():this.stopCheckAlive():null!=e.id&&null!=e.data?this.run(e):!0===e.kill&&(this.stopCheckAlive(),this.emitDestroy()))}workerReady(){!this.isMain&&this.sendToMainWorker({ready:!0,workerId:this.id})}startCheckAlive(){this.lastTaskTimestamp=r.performance.now(),this.aliveInterval=setInterval(this.checkAlive.bind(this),(this.opts.maxInactiveTime??U)/2),this.checkAlive.bind(this)()}stopCheckAlive(){null!=this.aliveInterval&&clearInterval(this.aliveInterval)}checkAlive(){r.performance.now()-this.lastTaskTimestamp>(this.opts.maxInactiveTime??U)&&this.sendToMainWorker({kill:this.opts.killBehavior,workerId:this.id})}getMainWorker(){if(null==this.mainWorker)throw new Error("Main worker not set");return this.mainWorker}handleError(e){return e instanceof Error?e.message:e}run(e){const t=this.getTaskFunction(e.name);(e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name)(t)?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.runSync.bind(this),this,t,e)}runSync(e,t){try{let s=this.beginTaskPerformance(t.name);const r=e(t.data);s=this.endTaskPerformance(s),this.sendToMainWorker({data:r,taskPerformance:s,workerId:this.id,id:t.id})}catch(e){const s=this.handleError(e);this.sendToMainWorker({taskError:{name:t.name??d,message:s,data:t.data},workerId:this.id,id:t.id})}finally{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())}}runAsync(e,t){let s=this.beginTaskPerformance(t.name);e(t.data).then((e=>(s=this.endTaskPerformance(s),this.sendToMainWorker({data:e,taskPerformance:s,workerId:this.id,id:t.id}),null))).catch((e=>{const s=this.handleError(e);this.sendToMainWorker({taskError:{name:t.name??d,message:s,data:t.data},workerId:this.id,id:t.id})})).finally((()=>{this.isMain||null==this.aliveInterval||(this.lastTaskTimestamp=r.performance.now())})).catch(m)}getTaskFunction(e){e=e??d;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??d,timestamp:r.performance.now(),...this.statistics.elu&&{elu:r.performance.eventLoopUtilization()}}}endTaskPerformance(e){return this.checkStatistics(),{...e,...this.statistics.runTime&&{runTime:r.performance.now()-e.timestamp},...this.statistics.elu&&{elu:r.performance.eventLoopUtilization(e.elu)}}}checkStatistics(){if(null==this.statistics)throw new Error("Performance statistics computation requirements not set")}}exports.ClusterWorker=class extends F{constructor(e,s={}){super("worker-cluster-pool:poolifier",t.isPrimary,e,t.worker,s)}get id(){return this.getMainWorker().id}sendToMainWorker(e){this.getMainWorker().send(e)}},exports.DynamicClusterPool=class extends A{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.DynamicThreadPool=class extends Q{max;constructor(e,t,s,r={}){super(e,s,r),this.max=t,this.checkDynamicPoolSize(this.numberOfWorkers,this.max)}get type(){return h.dynamic}get maxSize(){return this.max}get busy(){return this.full&&this.internalBusy()}},exports.FixedClusterPool=A,exports.FixedThreadPool=Q,exports.KillBehaviors=f,exports.Measurements=W,exports.PoolEvents=c,exports.PoolTypes=h,exports.ThreadWorker=class extends F{constructor(e,t={}){super("worker-thread-pool:poolifier",o.isMainThread,e,o.parentPort,t)}get id(){return o.threadId}sendToMainWorker(e){this.getMainWorker().postMessage(e)}handleError(e){return e}},exports.WorkerChoiceStrategies=y,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,4 +0,4 @@ | ||
import type { MessageValue, PromiseResponseWrapper } from '../utility-types'; | ||
import type { MessageValue, PromiseResponseWrapper, Task } from '../utility-types'; | ||
import { type IPool, PoolEmitter, type PoolInfo, type PoolOptions, type PoolType, type TasksQueueOptions } from './pool'; | ||
import type { IWorker, IWorkerNode, Task, WorkerType } from './worker'; | ||
import type { IWorker, IWorkerNode, WorkerType } from './worker'; | ||
import { type WorkerChoiceStrategy, type WorkerChoiceStrategyOptions } from './selection-strategies/selection-strategies-types'; | ||
@@ -5,0 +5,0 @@ import { WorkerChoiceStrategyContext } from './selection-strategies/worker-choice-strategy-context'; |
@@ -148,2 +148,4 @@ /** | ||
* Worker choice strategy interface. | ||
* | ||
* @internal | ||
*/ | ||
@@ -150,0 +152,0 @@ export interface IWorkerChoiceStrategy { |
@@ -1,1 +0,1 @@ | ||
export declare const version = "2.6.12"; | ||
export declare const version = "2.6.13"; |
@@ -1,2 +0,3 @@ | ||
import { type IWorker, type IWorkerNode, type Task, type WorkerInfo, type WorkerType, type WorkerUsage } from './worker'; | ||
import type { Task } from '../utility-types'; | ||
import { type IWorker, type IWorkerNode, type WorkerInfo, type WorkerType, type WorkerUsage } from './worker'; | ||
/** | ||
@@ -12,2 +13,3 @@ * Worker node. | ||
usage: WorkerUsage; | ||
private readonly tasksUsage; | ||
private readonly tasksQueue; | ||
@@ -19,3 +21,2 @@ /** | ||
* @param workerType - The worker type. | ||
* @internal | ||
*/ | ||
@@ -26,3 +27,3 @@ constructor(worker: Worker, workerType: WorkerType); | ||
/** | ||
* Worker node tasks queue maximum size. | ||
* Tasks queue maximum size. | ||
* | ||
@@ -38,5 +39,9 @@ * @returns The tasks queue maximum size. | ||
clearTasksQueue(): void; | ||
/** @inheritdoc */ | ||
resetUsage(): void; | ||
/** @inheritdoc */ | ||
getTaskWorkerUsage(name: string): WorkerUsage | undefined; | ||
private initWorkerInfo; | ||
private initWorkerUsage; | ||
private initTaskWorkerUsage; | ||
/** | ||
@@ -43,0 +48,0 @@ * Gets the worker id. |
import type { CircularArray } from '../circular-array'; | ||
import type { Task } from '../utility-types'; | ||
/** | ||
@@ -19,30 +20,2 @@ * Callback invoked if the worker has received a message. | ||
/** | ||
* Message object that is passed as a task between main worker and worker. | ||
* | ||
* @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. | ||
* @internal | ||
*/ | ||
export interface Task<Data = unknown> { | ||
/** | ||
* Worker id. | ||
*/ | ||
readonly workerId: number; | ||
/** | ||
* Task name. | ||
*/ | ||
readonly name?: string; | ||
/** | ||
* Task input data that will be passed to the worker. | ||
*/ | ||
readonly data?: Data; | ||
/** | ||
* Timestamp. | ||
*/ | ||
readonly timestamp?: number; | ||
/** | ||
* Message UUID. | ||
*/ | ||
readonly id?: string; | ||
} | ||
/** | ||
* Measurement statistics. | ||
@@ -109,3 +82,3 @@ * | ||
*/ | ||
readonly maxQueued: number; | ||
readonly maxQueued?: number; | ||
/** | ||
@@ -206,15 +179,15 @@ * Number of failed tasks. | ||
/** | ||
* Worker node worker. | ||
* Worker. | ||
*/ | ||
readonly worker: Worker; | ||
/** | ||
* Worker node worker info. | ||
* Worker info. | ||
*/ | ||
readonly info: WorkerInfo; | ||
/** | ||
* Worker node worker usage statistics. | ||
* Worker usage statistics. | ||
*/ | ||
usage: WorkerUsage; | ||
/** | ||
* Worker node tasks queue size. | ||
* Tasks queue size. | ||
* | ||
@@ -225,3 +198,3 @@ * @returns The tasks queue size. | ||
/** | ||
* Worker node enqueue task. | ||
* Enqueue task. | ||
* | ||
@@ -233,3 +206,3 @@ * @param task - The task to queue. | ||
/** | ||
* Worker node dequeue task. | ||
* Dequeue task. | ||
* | ||
@@ -240,9 +213,13 @@ * @returns The dequeued task. | ||
/** | ||
* Worker node clear tasks queue. | ||
* Clears tasks queue. | ||
*/ | ||
readonly clearTasksQueue: () => void; | ||
/** | ||
* Worker node reset usage statistics . | ||
* Resets usage statistics . | ||
*/ | ||
readonly resetUsage: () => void; | ||
/** | ||
* Gets task usage statistics. | ||
*/ | ||
readonly getTaskWorkerUsage: (name: string) => WorkerUsage | undefined; | ||
} |
@@ -37,2 +37,9 @@ /** | ||
clear(): void; | ||
/** | ||
* Returns an iterator for the queue. | ||
* | ||
* @returns An iterator for the queue. | ||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols | ||
*/ | ||
[Symbol.iterator](): Iterator<T>; | ||
} |
/// <reference types="node" /> | ||
import type { EventLoopUtilization } from 'node:perf_hooks'; | ||
import type { KillBehavior } from './worker/worker-options'; | ||
import type { IWorker, Task } from './pools/worker'; | ||
import type { IWorker } from './pools/worker'; | ||
/** | ||
@@ -12,2 +12,6 @@ * Task error. | ||
/** | ||
* Task name triggering the error. | ||
*/ | ||
readonly name: string; | ||
/** | ||
* Error message. | ||
@@ -17,3 +21,3 @@ */ | ||
/** | ||
* Data passed to the worker triggering the error. | ||
* Data triggering the error. | ||
*/ | ||
@@ -29,2 +33,6 @@ readonly data?: Data; | ||
/** | ||
* Task name. | ||
*/ | ||
readonly name: string; | ||
/** | ||
* Task performance timestamp. | ||
@@ -52,2 +60,30 @@ */ | ||
/** | ||
* Message object that is passed as a task between main worker and worker. | ||
* | ||
* @typeParam Data - Type of data sent to the worker. This can only be structured-cloneable data. | ||
* @internal | ||
*/ | ||
export interface Task<Data = unknown> { | ||
/** | ||
* Worker id. | ||
*/ | ||
readonly workerId: number; | ||
/** | ||
* Task name. | ||
*/ | ||
readonly name?: string; | ||
/** | ||
* Task input data that will be passed to the worker. | ||
*/ | ||
readonly data?: Data; | ||
/** | ||
* Timestamp. | ||
*/ | ||
readonly timestamp?: number; | ||
/** | ||
* Message UUID. | ||
*/ | ||
readonly id?: string; | ||
} | ||
/** | ||
* Message object that is passed between main worker and worker. | ||
@@ -54,0 +90,0 @@ * |
import type { MeasurementStatisticsRequirements, WorkerChoiceStrategyOptions } from './pools/selection-strategies/selection-strategies-types'; | ||
/** | ||
* Default task name. | ||
*/ | ||
export declare const DEFAULT_TASK_NAME = "default"; | ||
/** | ||
* An intentional empty function. | ||
@@ -4,0 +8,0 @@ */ |
@@ -8,3 +8,3 @@ /// <reference types="node" /> | ||
import type { MessagePort } from 'node:worker_threads'; | ||
import type { MessageValue, WorkerStatistics } from '../utility-types'; | ||
import type { MessageValue, Task, WorkerStatistics } from '../utility-types'; | ||
import { type WorkerOptions } from './worker-options'; | ||
@@ -61,2 +61,42 @@ import type { TaskFunctions, WorkerAsyncFunction, WorkerFunction, WorkerSyncFunction } from './worker-functions'; | ||
/** | ||
* Checks if the worker has a task function with the given name. | ||
* | ||
* @param name - The name of the task function to check. | ||
* @returns Whether the worker has a task function with the given name or not. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string. | ||
*/ | ||
hasTaskFunction(name: string): boolean; | ||
/** | ||
* Adds a task function to the worker. | ||
* If a task function with the same name already exists, it is replaced. | ||
* | ||
* @param name - The name of the task function to add. | ||
* @param fn - The task function to add. | ||
* @returns Whether the task function was added or not. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the `name` parameter is the default task function reserved name. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `fn` parameter is not a function. | ||
*/ | ||
addTaskFunction(name: string, fn: WorkerFunction<Data, Response>): boolean; | ||
/** | ||
* Removes a task function from the worker. | ||
* | ||
* @param name - The name of the task function to remove. | ||
* @returns Whether the task function existed and was removed or not. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the `name` parameter is the default task function reserved name. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the `name` parameter is the task function used as default task function. | ||
*/ | ||
removeTaskFunction(name: string): boolean; | ||
/** | ||
* Sets the default task function to use when no task function name is specified. | ||
* | ||
* @param name - The name of the task function to use as default task function. | ||
* @returns Whether the default task function was set or not. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-typeerror} If the `name` parameter is not a string. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the `name` parameter is the default task function reserved name. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the `name` parameter is a non-existing task function. | ||
*/ | ||
setDefaultTaskFunction(name: string): boolean; | ||
/** | ||
* Worker message listener. | ||
@@ -103,20 +143,29 @@ * | ||
/** | ||
* Runs the given function synchronously. | ||
* Runs the given task. | ||
* | ||
* @param fn - Function that will be executed. | ||
* @param message - Input data for the given function. | ||
* @param task - The task to execute. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the task function is not found. | ||
*/ | ||
protected runSync(fn: WorkerSyncFunction<Data, Response>, message: MessageValue<Data>): void; | ||
protected run(task: Task<Data>): void; | ||
/** | ||
* Runs the given function asynchronously. | ||
* Runs the given task function synchronously. | ||
* | ||
* @param fn - Function that will be executed. | ||
* @param message - Input data for the given function. | ||
* @param fn - Task function that will be executed. | ||
* @param task - Input data for the task function. | ||
*/ | ||
protected runAsync(fn: WorkerAsyncFunction<Data, Response>, message: MessageValue<Data>): void; | ||
protected runSync(fn: WorkerSyncFunction<Data, Response>, task: Task<Data>): void; | ||
/** | ||
* Gets the task function in the given scope. | ||
* Runs the given task function asynchronously. | ||
* | ||
* @param name - Name of the function that will be returned. | ||
* @param fn - Task function that will be executed. | ||
* @param task - Input data for the task function. | ||
*/ | ||
protected runAsync(fn: WorkerAsyncFunction<Data, Response>, task: Task<Data>): void; | ||
/** | ||
* Gets the task function with the given name. | ||
* | ||
* @param name - Name of the task function that will be returned. | ||
* @returns The task function. | ||
* @throws {@link https://nodejs.org/api/errors.html#class-error} If the task function is not found. | ||
*/ | ||
private getTaskFunction; | ||
@@ -123,0 +172,0 @@ private beginTaskPerformance; |
{ | ||
"name": "poolifier", | ||
"version": "2.6.12", | ||
"version": "2.6.13", | ||
"description": "A fast, easy to use Node.js Worker Thread Pool and Cluster Pool implementation", | ||
@@ -83,3 +83,3 @@ "license": "MIT", | ||
"@commitlint/config-conventional": "^17.6.6", | ||
"@release-it/bumper": "^4.0.2", | ||
"@release-it/bumper": "^5.0.0", | ||
"@release-it/keep-a-changelog": "^3.1.0", | ||
@@ -86,0 +86,0 @@ "@rollup/plugin-terser": "^0.4.3", |
@@ -234,13 +234,13 @@ <div align="center"> | ||
`data` (optional) An object that you want to pass to your worker implementation | ||
`name` (optional) A string with the task function name that you want to execute on the worker. Default: `'default'` | ||
This method is available on both pool implementations and returns a promise. | ||
`name` (optional) A string with the task function name that you want to execute on the worker. Default: `'default'` | ||
This method is available on both pool implementations and returns a promise with the task function execution response. | ||
### `pool.destroy()` | ||
Destroy method is available on both pool implementations. | ||
This method will call the terminate method on each worker. | ||
This method is available on both pool implementations and will call the terminate method on each worker. | ||
### `class YourWorker extends ThreadWorker/ClusterWorker` | ||
`taskFunctions` (mandatory) The task function or task functions object that you want to execute on the worker | ||
`taskFunctions` (mandatory) The task function or task functions object `{ name_1: fn_1, ..., name_n, fn_n }` that you want to execute on the worker | ||
`opts` (optional) An object with these properties: | ||
@@ -260,2 +260,27 @@ | ||
#### `YourWorker.hasTaskFunction(name)` | ||
`name` (mandatory) The task function name | ||
This method is available on both worker implementations and returns a boolean. | ||
#### `YourWorker.addTaskFunction(name, fn)` | ||
`name` (mandatory) The task function name | ||
`fn` (mandatory) The task function | ||
This method is available on both worker implementations and returns a boolean. | ||
#### `YourWorker.removeTaskFunction(name)` | ||
`name` (mandatory) The task function name | ||
This method is available on both worker implementations and returns a boolean. | ||
#### `YourWorker.setDefaultTaskFunction(name)` | ||
`name` (mandatory) The task function name | ||
This method is available on both worker implementations and returns a boolean. | ||
## General guidance | ||
@@ -262,0 +287,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
208105
2477
342