node-worker-threads-pool-ts
Version:
Simple worker threads pool using Node's worker_threads module. Compatible with ES6+ Promise, Typescript, Async/Await.
103 lines • 3.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pool = void 0;
const events_1 = require("events");
const task_container_1 = require("./task-container");
const promise_with_timer_1 = require("./promise-with-timer");
class Pool extends events_1.EventEmitter {
constructor(size) {
super();
this._deprecated = false;
this._workers = [];
this._createWorker = null;
this._taskQueue = [];
if (typeof size !== "number") {
throw new TypeError('"size" must be the type of number!');
}
if (Number.isNaN(size)) {
throw new Error('"size" must not be NaN!');
}
if (size < 1) {
throw new RangeError('"size" must not be lower than 1!');
}
this._size = size;
this._addEventHandlers();
}
_addEventHandlers() {
this.on("worker-ready", (worker) => {
this._processTask(worker);
});
}
_addWorkerLifecycleHandlers(worker) {
worker.on("ready", (worker) => this.emit("worker-ready", worker));
worker.once("exit", (code) => {
if (this._deprecated || code === 0) {
return;
}
this._replaceWorker(worker);
});
}
_setWorkerCreator(getWorker) {
this._createWorker = () => {
const worker = getWorker();
this._addWorkerLifecycleHandlers(worker);
return worker;
};
}
_replaceWorker(worker) {
const i = this._workers.indexOf(worker);
this._workers[i] = this._createWorker();
}
_getIdleWorker() {
const worker = this._workers.find((worker) => worker.ready);
return worker ? worker : null;
}
_processTask(worker) {
const task = this._taskQueue.shift();
if (!task) {
return;
}
const { param, resolve, reject, taskConfig } = task;
worker
.run(param, taskConfig)
.then(resolve)
.catch((error) => {
if (promise_with_timer_1.isTimeoutError(error)) {
worker.terminate();
}
reject(error);
});
}
fill(getWorker) {
this._setWorkerCreator(getWorker);
const size = this._size;
for (let i = 0; i < size; i++) {
this._workers.push(this._createWorker());
}
}
runTask(param, taskConfig) {
if (this._deprecated) {
throw new Error("This pool is deprecated! Please use a new one.");
}
return new Promise((resolve, reject) => {
const task = new task_container_1.TaskContainer(param, resolve, reject, taskConfig);
this._taskQueue.push(task);
const worker = this._getIdleWorker();
if (worker) {
this._processTask(worker);
}
});
}
/**
* Destroy this pool and terminate all threads.
*/
async destroy() {
this._deprecated = true;
this.removeAllListeners();
const workers = this._workers;
this._workers = [];
await Promise.all(workers.map((worker) => worker.terminate()));
}
}
exports.Pool = Pool;
//# sourceMappingURL=pool.js.map