poolifier
Advanced tools
Comparing version 2.0.2 to 2.1.0
@@ -8,2 +8,15 @@ # Changelog | ||
## [2.1.0] - 2021-29-08 | ||
### Added | ||
- Add an optional pool option `messageHandler` to `PoolOptions<Worker>` for registering a message handler callback on each worker. | ||
### Breaking Changes | ||
- `AbstractWorker` class `maxInactiveTime`, `killBehavior` and `async` attributes have been removed in favour of the same ones in the worker options `opts` public attribute. | ||
- `AbstractWorker` class `lastTask` attribute have been renamed to `lastTaskTimestamp`. | ||
- `AbstractWorker` class `interval` attribute have been renamed to `aliveInterval`. | ||
- `AbstractWorker` class cannot be instantiated without specifying the `mainWorker` argument referencing the main worker. | ||
## [2.0.2] - 2021-12-05 | ||
@@ -10,0 +23,0 @@ |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("events"),r=require("cluster"),t=require("worker_threads"),s=require("async_hooks");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i,n=o(e);!function(e){e.FIXED="fixed",e.DYNAMIC="dynamic"}(i||(i={}));class a extends n.default{}const h=()=>{},c=Object.freeze({SOFT:"SOFT",HARD:"HARD"});const l=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LESS_RECENTLY_USED:"LESS_RECENTLY_USED"});class k{constructor(e){this.pool=e,this.nextWorkerIndex=0}choose(){const e=this.pool.workers[this.nextWorkerIndex];return this.nextWorkerIndex=this.pool.workers.length-1===this.nextWorkerIndex?0:this.nextWorkerIndex+1,e}}class u{constructor(e){this.pool=e}choose(){const e=this.pool.type===i.DYNAMIC;let r,t=1/0;for(const[s,o]of this.pool.tasks){if(!e&&0===o)return s;o<t&&(r=s,t=o)}return r}}class p{constructor(e,r,t=l.ROUND_ROBIN){this.pool=e,this.createDynamicallyWorkerCallback=r,this.workerChoiceStrategy=y.getWorkerChoiceStrategy(this.pool,t)}choose(){const e=this.pool.findFreeTasksMapEntry();return e?e[0]:this.pool.busy?this.workerChoiceStrategy.choose():this.createDynamicallyWorkerCallback()}}class d{constructor(e,r,t=l.ROUND_ROBIN){this.pool=e,this.createDynamicallyWorkerCallback=r,this.setWorkerChoiceStrategy(t)}getPoolWorkerChoiceStrategy(e=l.ROUND_ROBIN){return this.pool.type===i.DYNAMIC?new p(this.pool,this.createDynamicallyWorkerCallback,e):y.getWorkerChoiceStrategy(this.pool,e)}setWorkerChoiceStrategy(e){this.workerChoiceStrategy=this.getPoolWorkerChoiceStrategy(e)}execute(){return this.workerChoiceStrategy.choose()}}class y{static getWorkerChoiceStrategy(e,r=l.ROUND_ROBIN){switch(r){case l.ROUND_ROBIN:return new k(e);case l.LESS_RECENTLY_USED:return new u(e);default:throw new Error(`Worker choice strategy '${r}' not found`)}}}class W{constructor(e,r,t){if(this.numberOfWorkers=e,this.filePath=r,this.opts=t,this.workers=[],this.tasks=new Map,this.promiseMap=new Map,this.nextMessageId=0,!this.isMain())throw new Error("Cannot start a pool from a worker!");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),this.checkPoolOptions(this.opts),this.setupHook();for(let e=1;e<=this.numberOfWorkers;e++)this.createAndSetupWorker();this.opts.enableEvents&&(this.emitter=new a),this.workerChoiceStrategyContext=new d(this,(()=>{const e=this.createAndSetupWorker();return this.registerWorkerMessageListener(e,(async r=>{const t=this.tasks.get(e);var s;s=c.HARD,(r.kill===s||0===t)&&await this.destroyWorker(e)})),e}),this.opts.workerChoiceStrategy)}checkFilePath(e){if(!e)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 Error("Cannot instantiate a pool with a non integer number of workers");if(e<0)throw new Error("Cannot instantiate a pool with a negative number of workers");if(this.type===i.FIXED&&0===e)throw new Error("Cannot instantiate a fixed pool with no worker")}checkPoolOptions(e){var r,t;this.opts.workerChoiceStrategy=null!==(r=e.workerChoiceStrategy)&&void 0!==r?r:l.ROUND_ROBIN,this.opts.enableEvents=null===(t=e.enableEvents)||void 0===t||t}get numberOfRunningTasks(){return this.promiseMap.size}setWorkerChoiceStrategy(e){this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(e)}internalGetBusyStatus(){return this.numberOfRunningTasks>=this.numberOfWorkers&&!1===this.findFreeTasksMapEntry()}findFreeTasksMapEntry(){for(const[e,r]of this.tasks)if(0===r)return[e,r];return!1}execute(e){const r=this.chooseWorker(),t=++this.nextMessageId,s=this.internalExecute(r,t);return this.checkAndEmitBusy(),this.sendToWorker(r,{data:e||{},id:t}),s}async destroy(){await Promise.all(this.workers.map((e=>this.destroyWorker(e))))}setupHook(){}increaseWorkersTask(e){this.stepWorkerNumberOfTasks(e,1)}decreaseWorkersTasks(e){this.stepWorkerNumberOfTasks(e,-1)}stepWorkerNumberOfTasks(e,r){const t=this.tasks.get(e);if(void 0===t)throw Error("Worker could not be found in tasks map");this.tasks.set(e,t+r)}removeWorker(e){const r=this.workers.indexOf(e);this.workers.splice(r,1),this.tasks.delete(e)}chooseWorker(){return this.workerChoiceStrategyContext.execute()}internalExecute(e,r){return this.increaseWorkersTask(e),new Promise(((t,s)=>{this.promiseMap.set(r,{resolve:t,reject:s,worker:e})}))}createAndSetupWorker(){var e,r,t;const s=this.createWorker();return s.on("error",null!==(e=this.opts.errorHandler)&&void 0!==e?e:h),s.on("online",null!==(r=this.opts.onlineHandler)&&void 0!==r?r:h),s.on("exit",null!==(t=this.opts.exitHandler)&&void 0!==t?t:h),s.once("exit",(()=>this.removeWorker(s))),this.workers.push(s),this.tasks.set(s,0),this.afterWorkerSetup(s),s}workerListener(){return e=>{if(e.id){const r=this.promiseMap.get(e.id);r&&(this.decreaseWorkersTasks(r.worker),e.error?r.reject(e.error):r.resolve(e.data),this.promiseMap.delete(e.id))}}}checkAndEmitBusy(){var e;this.opts.enableEvents&&this.busy&&(null===(e=this.emitter)||void 0===e||e.emit("busy"))}}class w extends W{constructor(e,r,t={}){super(e,r,t),this.opts=t}setupHook(){r.setupMaster({exec:this.filePath})}isMain(){return r.isMaster}destroyWorker(e){this.sendToWorker(e,{kill:1}),e.kill()}sendToWorker(e,r){e.send(r)}registerWorkerMessageListener(e,r){e.on("message",r)}createWorker(){return r.fork(this.opts.env)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,super.workerListener())}get type(){return i.FIXED}get busy(){return this.internalGetBusyStatus()}}class g extends W{constructor(e,r,t={}){super(e,r,t)}isMain(){return t.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:1}),await e.terminate()}sendToWorker(e,r){e.postMessage(r)}registerWorkerMessageListener(e,r){var t;null===(t=e.port2)||void 0===t||t.on("message",r)}createWorker(){return new t.Worker(this.filePath,{env:t.SHARE_ENV})}afterWorkerSetup(e){const{port1:r,port2:s}=new t.MessageChannel;e.postMessage({parent:r},[r]),e.port1=r,e.port2=s,this.registerWorkerMessageListener(e,super.workerListener())}get type(){return i.FIXED}get busy(){return this.internalGetBusyStatus()}}const m=c.SOFT;class f extends s.AsyncResource{constructor(e,r,t,s,o={killBehavior:m,maxInactiveTime:6e4}){var i,n,a;super(e),this.mainWorker=s,this.opts=o,this.killBehavior=null!==(i=this.opts.killBehavior)&&void 0!==i?i:m,this.maxInactiveTime=null!==(n=this.opts.maxInactiveTime)&&void 0!==n?n:6e4,this.async=!!this.opts.async,this.lastTask=Date.now(),this.checkFunctionInput(t),r||(this.interval=setInterval(this.checkAlive.bind(this),this.maxInactiveTime/2),this.checkAlive.bind(this)()),null===(a=this.mainWorker)||void 0===a||a.on("message",(e=>{(null==e?void 0:e.data)&&e.id?this.async?this.runInAsyncScope(this.runAsync.bind(this),this,t,e):this.runInAsyncScope(this.run.bind(this),this,t,e):e.parent?this.mainWorker=e.parent:e.kill&&(this.interval&&clearInterval(this.interval),this.emitDestroy())}))}checkFunctionInput(e){if(!e)throw new Error("fn parameter is mandatory")}getMainWorker(){if(!this.mainWorker)throw new Error("Main worker was not set");return this.mainWorker}checkAlive(){Date.now()-this.lastTask>this.maxInactiveTime&&this.sendToMainWorker({kill:this.killBehavior})}handleError(e){return e}run(e,r){try{const t=e(r.data);this.sendToMainWorker({data:t,id:r.id})}catch(e){const t=this.handleError(e);this.sendToMainWorker({error:t,id:r.id})}finally{this.lastTask=Date.now()}}runAsync(e,r){e(r.data).then((e=>(this.sendToMainWorker({data:e,id:r.id}),null))).catch((e=>{const t=this.handleError(e);this.sendToMainWorker({error:t,id:r.id})})).finally((()=>{this.lastTask=Date.now()})).catch(h)}}exports.AbstractWorker=f,exports.ClusterWorker=class extends f{constructor(e,t={}){super("worker-cluster-pool:pioardi",r.isMaster,e,r.worker,t)}sendToMainWorker(e){this.getMainWorker().send(e)}handleError(e){return e instanceof Error?e.message:e}},exports.DynamicClusterPool=class extends w{constructor(e,r,t,s={}){super(e,t,s),this.max=r}get type(){return i.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.DynamicThreadPool=class extends g{constructor(e,r,t,s={}){super(e,t,s),this.max=r}get type(){return i.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.FixedClusterPool=w,exports.FixedThreadPool=g,exports.KillBehaviors=c,exports.ThreadWorker=class extends f{constructor(e,r={}){super("worker-thread-pool:pioardi",t.isMainThread,e,t.parentPort,r)}sendToMainWorker(e){this.getMainWorker().postMessage(e)}},exports.WorkerChoiceStrategies=l; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("events"),t=require("cluster"),r=require("worker_threads"),s=require("async_hooks");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var i,n=o(e);!function(e){e.FIXED="fixed",e.DYNAMIC="dynamic"}(i||(i={}));class a extends n.default{}const h=()=>{},c=Object.freeze({SOFT:"SOFT",HARD:"HARD"});const l=Object.freeze({ROUND_ROBIN:"ROUND_ROBIN",LESS_RECENTLY_USED:"LESS_RECENTLY_USED"});class k{constructor(e){this.pool=e,this.nextWorkerIndex=0}choose(){const e=this.pool.workers[this.nextWorkerIndex];return this.nextWorkerIndex=this.pool.workers.length-1===this.nextWorkerIndex?0:this.nextWorkerIndex+1,e}}class u{constructor(e){this.pool=e}choose(){const e=this.pool.type===i.DYNAMIC;let t,r=1/0;for(const[s,o]of this.pool.tasks){if(!e&&0===o)return s;o<r&&(t=s,r=o)}return t}}class p{constructor(e,t,r=l.ROUND_ROBIN){this.pool=e,this.createDynamicallyWorkerCallback=t,this.workerChoiceStrategy=W.getWorkerChoiceStrategy(this.pool,r)}choose(){const e=this.pool.findFreeTasksMapEntry();return e?e[0]:this.pool.busy?this.workerChoiceStrategy.choose():this.createDynamicallyWorkerCallback()}}class d{constructor(e,t,r=l.ROUND_ROBIN){this.pool=e,this.createDynamicallyWorkerCallback=t,this.setWorkerChoiceStrategy(r)}getPoolWorkerChoiceStrategy(e=l.ROUND_ROBIN){return this.pool.type===i.DYNAMIC?new p(this.pool,this.createDynamicallyWorkerCallback,e):W.getWorkerChoiceStrategy(this.pool,e)}setWorkerChoiceStrategy(e){this.workerChoiceStrategy=this.getPoolWorkerChoiceStrategy(e)}execute(){return this.workerChoiceStrategy.choose()}}class W{static getWorkerChoiceStrategy(e,t=l.ROUND_ROBIN){switch(t){case l.ROUND_ROBIN:return new k(e);case l.LESS_RECENTLY_USED:return new u(e);default:throw new Error(`Worker choice strategy '${t}' not found`)}}}class y{constructor(e,t,r){if(this.numberOfWorkers=e,this.filePath=t,this.opts=r,this.workers=[],this.tasks=new Map,this.promiseMap=new Map,this.nextMessageId=0,!this.isMain())throw new Error("Cannot start a pool from a worker!");this.checkNumberOfWorkers(this.numberOfWorkers),this.checkFilePath(this.filePath),this.checkPoolOptions(this.opts),this.setupHook();for(let e=1;e<=this.numberOfWorkers;e++)this.createAndSetupWorker();this.opts.enableEvents&&(this.emitter=new a),this.workerChoiceStrategyContext=new d(this,(()=>{const e=this.createAndSetupWorker();return this.registerWorkerMessageListener(e,(async t=>{const r=this.tasks.get(e);var s;s=c.HARD,(t.kill===s||0===r)&&await this.destroyWorker(e)})),e}),this.opts.workerChoiceStrategy)}checkFilePath(e){if(!e)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 Error("Cannot instantiate a pool with a non integer number of workers");if(e<0)throw new Error("Cannot instantiate a pool with a negative number of workers");if(this.type===i.FIXED&&0===e)throw new Error("Cannot instantiate a fixed pool with no worker")}checkPoolOptions(e){var t,r;this.opts.workerChoiceStrategy=null!==(t=e.workerChoiceStrategy)&&void 0!==t?t:l.ROUND_ROBIN,this.opts.enableEvents=null===(r=e.enableEvents)||void 0===r||r}get numberOfRunningTasks(){return this.promiseMap.size}setWorkerChoiceStrategy(e){this.opts.workerChoiceStrategy=e,this.workerChoiceStrategyContext.setWorkerChoiceStrategy(e)}internalGetBusyStatus(){return this.numberOfRunningTasks>=this.numberOfWorkers&&!1===this.findFreeTasksMapEntry()}findFreeTasksMapEntry(){for(const[e,t]of this.tasks)if(0===t)return[e,t];return!1}execute(e){const t=this.chooseWorker(),r=++this.nextMessageId,s=this.internalExecute(t,r);return this.checkAndEmitBusy(),this.sendToWorker(t,{data:e||{},id:r}),s}async destroy(){await Promise.all(this.workers.map((e=>this.destroyWorker(e))))}setupHook(){}increaseWorkersTask(e){this.stepWorkerNumberOfTasks(e,1)}decreaseWorkersTasks(e){this.stepWorkerNumberOfTasks(e,-1)}stepWorkerNumberOfTasks(e,t){const r=this.tasks.get(e);if(void 0===r)throw Error("Worker could not be found in tasks map");this.tasks.set(e,r+t)}removeWorker(e){const t=this.workers.indexOf(e);this.workers.splice(t,1),this.tasks.delete(e)}chooseWorker(){return this.workerChoiceStrategyContext.execute()}internalExecute(e,t){return this.increaseWorkersTask(e),new Promise(((r,s)=>{this.promiseMap.set(t,{resolve:r,reject:s,worker:e})}))}createAndSetupWorker(){var e,t,r,s;const o=this.createWorker();return o.on("message",null!==(e=this.opts.messageHandler)&&void 0!==e?e:h),o.on("error",null!==(t=this.opts.errorHandler)&&void 0!==t?t:h),o.on("online",null!==(r=this.opts.onlineHandler)&&void 0!==r?r:h),o.on("exit",null!==(s=this.opts.exitHandler)&&void 0!==s?s:h),o.once("exit",(()=>this.removeWorker(o))),this.workers.push(o),this.tasks.set(o,0),this.afterWorkerSetup(o),o}workerListener(){return e=>{if(e.id){const t=this.promiseMap.get(e.id);t&&(this.decreaseWorkersTasks(t.worker),e.error?t.reject(e.error):t.resolve(e.data),this.promiseMap.delete(e.id))}}}checkAndEmitBusy(){var e;this.opts.enableEvents&&this.busy&&(null===(e=this.emitter)||void 0===e||e.emit("busy"))}}class w extends y{constructor(e,t,r={}){super(e,t,r),this.opts=r}setupHook(){t.setupMaster({exec:this.filePath})}isMain(){return t.isMaster}destroyWorker(e){this.sendToWorker(e,{kill:1}),e.kill()}sendToWorker(e,t){e.send(t)}registerWorkerMessageListener(e,t){e.on("message",t)}createWorker(){return t.fork(this.opts.env)}afterWorkerSetup(e){this.registerWorkerMessageListener(e,super.workerListener())}get type(){return i.FIXED}get busy(){return this.internalGetBusyStatus()}}class m extends y{constructor(e,t,r={}){super(e,t,r)}isMain(){return r.isMainThread}async destroyWorker(e){this.sendToWorker(e,{kill:1}),await e.terminate()}sendToWorker(e,t){e.postMessage(t)}registerWorkerMessageListener(e,t){var r;null===(r=e.port2)||void 0===r||r.on("message",t)}createWorker(){return new r.Worker(this.filePath,{env:r.SHARE_ENV})}afterWorkerSetup(e){const{port1:t,port2:s}=new r.MessageChannel;e.postMessage({parent:t},[t]),e.port1=t,e.port2=s,this.registerWorkerMessageListener(e,super.workerListener())}get type(){return i.FIXED}get busy(){return this.internalGetBusyStatus()}}const g=c.SOFT;class f extends s.AsyncResource{constructor(e,t,r,s,o={killBehavior:g,maxInactiveTime:6e4}){var i,n;super(e),this.mainWorker=s,this.opts=o,this.checkFunctionInput(r),this.checkWorkerOptions(this.opts),this.lastTaskTimestamp=Date.now(),t||(this.aliveInterval=setInterval(this.checkAlive.bind(this),(null!==(i=this.opts.maxInactiveTime)&&void 0!==i?i:6e4)/2),this.checkAlive.bind(this)()),null===(n=this.mainWorker)||void 0===n||n.on("message",(e=>{(null==e?void 0:e.data)&&e.id?this.opts.async?this.runInAsyncScope(this.runAsync.bind(this),this,r,e):this.runInAsyncScope(this.run.bind(this),this,r,e):e.parent?this.mainWorker=e.parent:e.kill&&(this.aliveInterval&&clearInterval(this.aliveInterval),this.emitDestroy())}))}checkWorkerOptions(e){var t,r;this.opts.killBehavior=null!==(t=e.killBehavior)&&void 0!==t?t:g,this.opts.maxInactiveTime=null!==(r=e.maxInactiveTime)&&void 0!==r?r:6e4,this.opts.async=!!e.async}checkFunctionInput(e){if(!e)throw new Error("fn parameter is mandatory")}getMainWorker(){if(!this.mainWorker)throw new Error("Main worker was not set");return this.mainWorker}checkAlive(){var e;Date.now()-this.lastTaskTimestamp>(null!==(e=this.opts.maxInactiveTime)&&void 0!==e?e:6e4)&&this.sendToMainWorker({kill:this.opts.killBehavior})}handleError(e){return e}run(e,t){try{const r=e(t.data);this.sendToMainWorker({data:r,id:t.id})}catch(e){const r=this.handleError(e);this.sendToMainWorker({error:r,id:t.id})}finally{this.lastTaskTimestamp=Date.now()}}runAsync(e,t){e(t.data).then((e=>(this.sendToMainWorker({data:e,id:t.id}),null))).catch((e=>{const r=this.handleError(e);this.sendToMainWorker({error:r,id:t.id})})).finally((()=>{this.lastTaskTimestamp=Date.now()})).catch(h)}}exports.AbstractWorker=f,exports.ClusterWorker=class extends f{constructor(e,r={}){super("worker-cluster-pool:poolifier",t.isMaster,e,t.worker,r)}sendToMainWorker(e){this.getMainWorker().send(e)}handleError(e){return e instanceof Error?e.message:e}},exports.DynamicClusterPool=class extends w{constructor(e,t,r,s={}){super(e,r,s),this.max=t}get type(){return i.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.DynamicThreadPool=class extends m{constructor(e,t,r,s={}){super(e,r,s),this.max=t}get type(){return i.DYNAMIC}get busy(){return this.workers.length===this.max}},exports.FixedClusterPool=w,exports.FixedThreadPool=m,exports.KillBehaviors=c,exports.ThreadWorker=class extends f{constructor(e,t={}){super("worker-thread-pool:poolifier",r.isMainThread,e,r.parentPort,t)}sendToMainWorker(e){this.getMainWorker().postMessage(e)}},exports.WorkerChoiceStrategies=l; |
@@ -7,2 +7,6 @@ import type { MessageValue, PromiseWorkerResponseWrapper } from '../utility-types'; | ||
/** | ||
* Callback invoked if the worker has received a message. | ||
*/ | ||
export declare type MessageHandler<Worker> = (this: Worker, m: unknown) => void; | ||
/** | ||
* Callback invoked if the worker raised an error. | ||
@@ -24,2 +28,9 @@ */ | ||
/** | ||
* Register a listener to the message event. | ||
* | ||
* @param event `'message'`. | ||
* @param handler The message handler. | ||
*/ | ||
on(event: 'message', handler: MessageHandler<this>): void; | ||
/** | ||
* Register a listener to the error event. | ||
@@ -58,2 +69,6 @@ * | ||
/** | ||
* A function that will listen for message event on each worker. | ||
*/ | ||
messageHandler?: MessageHandler<Worker>; | ||
/** | ||
* A function that will listen for error event on each worker. | ||
@@ -77,3 +92,3 @@ */ | ||
* | ||
* Default to true. | ||
* @default true | ||
*/ | ||
@@ -104,3 +119,3 @@ enableEvents?: boolean; | ||
* | ||
* - `key`: This is the message ID of each submitted task. | ||
* - `key`: This is the message Id of each submitted task. | ||
* - `value`: An object that contains the worker, the resolve function and the reject function. | ||
@@ -112,3 +127,3 @@ * | ||
/** | ||
* ID of the next message. | ||
* Id of the next message. | ||
*/ | ||
@@ -164,3 +179,3 @@ protected nextMessageId: number; | ||
/** | ||
* Increase the number of tasks that the given workers has applied. | ||
* Increase the number of tasks that the given worker has applied. | ||
* | ||
@@ -171,3 +186,3 @@ * @param worker Worker whose tasks are increased. | ||
/** | ||
* Decrease the number of tasks that the given workers has applied. | ||
* Decrease the number of tasks that the given worker has applied. | ||
* | ||
@@ -178,3 +193,3 @@ * @param worker Worker whose tasks are decreased. | ||
/** | ||
* Step the number of tasks that the given workers has applied. | ||
* Step the number of tasks that the given worker has applied. | ||
* | ||
@@ -181,0 +196,0 @@ * @param worker Worker whose tasks are set. |
@@ -10,5 +10,4 @@ import { PoolType } from '../pool-internal'; | ||
* | ||
* @template Data Type of data sent to the worker. This can only be serializable data. | ||
* @template Response Type of response of execution. This can only be serializable data. | ||
* | ||
* @template DataType of data sent to the worker. This can only be serializable data. | ||
* @template ResponseType of response of execution. This can only be serializable data. | ||
* @author [Christopher Quadflieg](https://github.com/Shinigami92) | ||
@@ -25,3 +24,3 @@ * @since 2.0.0 | ||
* @param filePath Path to an implementation of a `ClusterWorker` file, which can be relative or absolute. | ||
* @param opts Options for this dynamic cluster pool. Default: `{}` | ||
* @param [opts={}] Options for this dynamic cluster pool. | ||
*/ | ||
@@ -28,0 +27,0 @@ constructor(min: number, max: number, filePath: string, opts?: ClusterPoolOptions); |
@@ -25,5 +25,4 @@ /// <reference types="node" /> | ||
* | ||
* @template Data Type of data sent to the worker. This can only be serializable data. | ||
* @template Response Type of response of execution. This can only be serializable data. | ||
* | ||
* @template DataType of data sent to the worker. This can only be serializable data. | ||
* @template ResponseType of response of execution. This can only be serializable data. | ||
* @author [Christopher Quadflieg](https://github.com/Shinigami92) | ||
@@ -39,3 +38,3 @@ * @since 2.0.0 | ||
* @param filePath Path to an implementation of a `ClusterWorker` file, which can be relative or absolute. | ||
* @param opts Options for this fixed cluster pool. Default: `{}` | ||
* @param [opts={}] Options for this fixed cluster pool. | ||
*/ | ||
@@ -42,0 +41,0 @@ constructor(numberOfWorkers: number, filePath: string, opts?: ClusterPoolOptions); |
@@ -11,5 +11,4 @@ import type { PoolOptions } from '../abstract-pool'; | ||
* | ||
* @template Data Type of data sent to the worker. This can only be serializable data. | ||
* @template Response Type of response of execution. This can only be serializable data. | ||
* | ||
* @template DataType of data sent to the worker. This can only be serializable data. | ||
* @template ResponseType of response of execution. This can only be serializable data. | ||
* @author [Alessandro Pio Ardizio](https://github.com/pioardi) | ||
@@ -26,3 +25,3 @@ * @since 0.0.1 | ||
* @param filePath Path to an implementation of a `ThreadWorker` file, which can be relative or absolute. | ||
* @param opts Options for this dynamic thread pool. Default: `{}` | ||
* @param [opts={}] Options for this dynamic thread pool. | ||
*/ | ||
@@ -29,0 +28,0 @@ constructor(min: number, max: number, filePath: string, opts?: PoolOptions<ThreadWorkerWithMessageChannel>); |
@@ -18,5 +18,4 @@ /// <reference types="node" /> | ||
* | ||
* @template Data Type of data sent to the worker. This can only be serializable data. | ||
* @template Response Type of response of execution. This can only be serializable data. | ||
* | ||
* @template DataType of data sent to the worker. This can only be serializable data. | ||
* @template ResponseType of response of execution. This can only be serializable data. | ||
* @author [Alessandro Pio Ardizio](https://github.com/pioardi) | ||
@@ -31,3 +30,3 @@ * @since 0.0.1 | ||
* @param filePath Path to an implementation of a `ThreadWorker` file, which can be relative or absolute. | ||
* @param opts Options for this fixed thread pool. Default: `{}` | ||
* @param [opts={}] Options for this fixed thread pool. | ||
*/ | ||
@@ -34,0 +33,0 @@ constructor(numberOfThreads: number, filePath: string, opts?: PoolOptions<ThreadWorkerWithMessageChannel>); |
@@ -21,3 +21,3 @@ /// <reference types="node" /> | ||
/** | ||
* ID of the message. | ||
* Id of the message. | ||
*/ | ||
@@ -24,0 +24,0 @@ readonly id?: number; |
@@ -6,3 +6,3 @@ /// <reference types="node" /> | ||
import type { MessageValue } from '../utility-types'; | ||
import type { KillBehavior, WorkerOptions } from './worker-options'; | ||
import type { WorkerOptions } from './worker-options'; | ||
/** | ||
@@ -16,24 +16,12 @@ * Base class containing some shared logic for all poolifier workers. | ||
export declare abstract class AbstractWorker<MainWorker extends Worker | MessagePort, Data = unknown, Response = unknown> extends AsyncResource { | ||
protected mainWorker?: MainWorker | null | undefined; | ||
protected mainWorker: MainWorker | null; | ||
readonly opts: WorkerOptions; | ||
/** | ||
* The maximum time to keep this worker alive while idle. The pool automatically checks and terminates this worker when the time expires. | ||
*/ | ||
protected readonly maxInactiveTime: number; | ||
/** | ||
* The kill behavior set as option on the Worker constructor or a default value. | ||
*/ | ||
protected readonly killBehavior: KillBehavior; | ||
/** | ||
* Whether the worker is working asynchronously or not. | ||
*/ | ||
protected readonly async: boolean; | ||
/** | ||
* Timestamp of the last task processed by this worker. | ||
*/ | ||
protected lastTask: number; | ||
protected lastTaskTimestamp: number; | ||
/** | ||
* Handler ID of the `interval` alive check. | ||
* Handler Id of the `aliveInterval` worker alive check. | ||
*/ | ||
protected readonly interval?: NodeJS.Timeout; | ||
protected readonly aliveInterval?: NodeJS.Timeout; | ||
/** | ||
@@ -48,3 +36,4 @@ * Constructs a new poolifier worker. | ||
*/ | ||
constructor(type: string, isMain: boolean, fn: (data: Data) => Response, mainWorker?: MainWorker | null | undefined, opts?: WorkerOptions); | ||
constructor(type: string, isMain: boolean, fn: (data: Data) => Response, mainWorker: MainWorker | null, opts?: WorkerOptions); | ||
private checkWorkerOptions; | ||
/** | ||
@@ -51,0 +40,0 @@ * Check if the `fn` parameter is passed to the constructor. |
@@ -15,5 +15,4 @@ /// <reference types="node" /> | ||
* | ||
* @template Data Type of data this worker receives from pool's execution. This can only be serializable data. | ||
* @template Response Type of response the worker sends back to the main worker. This can only be serializable data. | ||
* | ||
* @template DataType of data this worker receives from pool's execution. This can only be serializable data. | ||
* @template ResponseType of response the worker sends back to the main worker. This can only be serializable data. | ||
* @author [Christopher Quadflieg](https://github.com/Shinigami92) | ||
@@ -20,0 +19,0 @@ * @since 2.0.0 |
@@ -15,5 +15,4 @@ /// <reference types="node" /> | ||
* | ||
* @template Data Type of data this worker receives from pool's execution. This can only be serializable data. | ||
* @template Response Type of response the worker sends back to the main thread. This can only be serializable data. | ||
* | ||
* @template DataType of data this worker receives from pool's execution. This can only be serializable data. | ||
* @template ResponseType of response the worker sends back to the main thread. This can only be serializable data. | ||
* @author [Alessandro Pio Ardizio](https://github.com/pioardi) | ||
@@ -20,0 +19,0 @@ * @since 0.0.1 |
{ | ||
"name": "poolifier", | ||
"version": "2.0.2", | ||
"version": "2.1.0", | ||
"description": "A fast, easy to use Node.js Worker Thread Pool and Cluster Pool implementation", | ||
@@ -13,6 +13,5 @@ "main": "lib/index.js", | ||
"benchmark:prod": "npm run build:prod && node -r source-map-support/register benchmarks/internal/bench.js", | ||
"test": "npm run build && nyc mocha --parallel 'tests/**/*.test.js'", | ||
"test:debug": "npm run build && mocha --inspect 'tests/**/*.test.js'", | ||
"test:prod": "npm run build:prod && nyc mocha --parallel 'tests/**/*.test.js'", | ||
"sonar": "sonar-scanner", | ||
"test": "npm run build && nyc mocha 'tests/**/*.test.js'", | ||
"test:debug": "npm run build && mocha --no-parallel --inspect 'tests/**/*.test.js'", | ||
"test:prod": "npm run build:prod && nyc mocha 'tests/**/*.test.js'", | ||
"coverage": "nyc report --reporter=lcov", | ||
@@ -28,3 +27,3 @@ "coverage:html": "nyc report --reporter=html", | ||
"type": "git", | ||
"url": "git+https://github.com/pioardi/poolifier.git" | ||
"url": "git+https://github.com/poolifier/poolifier.git" | ||
}, | ||
@@ -61,5 +60,5 @@ "keywords": [ | ||
"bugs": { | ||
"url": "https://github.com/pioardi/poolifier/issues" | ||
"url": "https://github.com/poolifier/poolifier/issues" | ||
}, | ||
"homepage": "https://github.com/pioardi/poolifier#readme", | ||
"homepage": "https://github.com/poolifier/poolifier#readme", | ||
"files": [ | ||
@@ -69,23 +68,24 @@ "lib" | ||
"devDependencies": { | ||
"@types/node": "^14.14.44", | ||
"@typescript-eslint/eslint-plugin": "^4.23.0", | ||
"@typescript-eslint/parser": "^4.23.0", | ||
"@types/node": "^14.17.12", | ||
"@typescript-eslint/eslint-plugin": "^4.29.3", | ||
"@typescript-eslint/parser": "^4.29.3", | ||
"benchmark": "^2.1.4", | ||
"eslint": "^7.26.0", | ||
"eslint-config-standard": "^16.0.2", | ||
"eslint-define-config": "^1.0.8", | ||
"eslint-plugin-import": "^2.22.1", | ||
"eslint-plugin-jsdoc": "^34.0.2", | ||
"eslint": "^7.32.0", | ||
"eslint-config-standard": "^16.0.3", | ||
"eslint-define-config": "^1.0.9", | ||
"eslint-plugin-import": "^2.24.2", | ||
"eslint-plugin-jsdoc": "^36.0.8", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-prettierx": "^0.17.1", | ||
"eslint-plugin-prettierx": "^0.18.0", | ||
"eslint-plugin-promise": "^5.1.0", | ||
"eslint-plugin-spellcheck": "0.0.17", | ||
"expect": "^26.6.2", | ||
"eslint-plugin-spellcheck": "0.0.19", | ||
"expect": "^27.1.0", | ||
"microtime": "^3.0.0", | ||
"mocha": "^8.4.0", | ||
"mocha": "^9.1.1", | ||
"mochawesome": "^6.2.2", | ||
"nyc": "^15.1.0", | ||
"prettier": "^2.3.0", | ||
"prettier-plugin-organize-imports": "^2.0.0", | ||
"prettierx": "^0.18.0", | ||
"rollup": "^2.47.0", | ||
"prettier": "^2.3.2", | ||
"prettier-plugin-organize-imports": "^2.3.3", | ||
"prettierx": "^0.19.0", | ||
"rollup": "^2.56.3", | ||
"rollup-plugin-analyzer": "^4.0.0", | ||
@@ -97,6 +97,5 @@ "rollup-plugin-command": "^1.1.3", | ||
"rollup-plugin-typescript2": "^0.30.0", | ||
"sonar-scanner": "^3.1.0", | ||
"source-map-support": "^0.5.19", | ||
"typedoc": "^0.20.36", | ||
"typescript": "^4.2.4" | ||
"typedoc": "^0.21.8", | ||
"typescript": "^4.4.2" | ||
}, | ||
@@ -103,0 +102,0 @@ "engines": { |
@@ -14,4 +14,4 @@ <div align="center"> | ||
<img alt="Weekly Downloads" src="https://img.shields.io/npm/dw/poolifier"></a> | ||
<a href="https://github.com/pioardi/node-pool/actions"> | ||
<img alt="Actions Status" src="https://github.com/pioardi/node-pool/workflows/NodeCI/badge.svg"></a> | ||
<a href="https://github.com/poolifier/poolifier/actions"> | ||
<img alt="Actions Status" src="https://github.com/poolifier/poolifier/workflows/NodeCI/badge.svg"></a> | ||
<a href="https://sonarcloud.io/dashboard?id=pioardi_poolifier"> | ||
@@ -248,3 +248,3 @@ <img alt="Quality Gate Status" src="https://sonarcloud.io/api/project_badges/measure?project=pioardi_poolifier&metric=alert_status"></a> | ||
See guidelines [CONTRIBUTING](CONTRIBUTING.md) | ||
Choose your task here [2.0.0](https://github.com/pioardi/poolifier/projects/1), propose an idea, a fix, an improvement. | ||
Choose your task here [2.0.0](https://github.com/poolifier/poolifier/projects/1), propose an idea, a fix, an improvement. | ||
@@ -251,0 +251,0 @@ ## Team |
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
64687
883