expressmultithread
Version:
Fast, light-weight and low dependency [Express.js](https://www.npmjs.com/package/express) multithreaded router.
153 lines • 5.39 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Instance = void 0;
const worker_threads_1 = require("worker_threads");
const types_1 = require("../types");
const config_1 = __importDefault(require("../config"));
const strings_1 = require("../constants/strings");
const postMessage_1 = require("../functions/utils/postMessage");
const compareArray_1 = require("../functions/utils/compareArray");
class Parent {
constructor(threadCount = config_1.default.threadCount) {
this.childs = [];
this._sources = [];
this.inc = 0;
for (let i = 0; i < threadCount; i++) {
this.newChild();
}
}
;
newChild() {
this.inc++;
config_1.default.verbose && console.info("Starting thread id :", this.inc);
const child = new worker_threads_1.Worker(__dirname + strings_1.slash + strings_1.childFile, {
workerData: {
id: this.inc
}
});
child.on(strings_1.message, (data) => {
const parsed = JSON.parse(data);
const z = this.childs.findIndex(child => child.id === parsed.id);
if (z === -1)
throw new Error(strings_1.childNotFound);
switch (parsed.cmd) {
case types_1.ChildCmd.ready:
this.childs[z].ready = true;
break;
case types_1.ChildCmd.response:
const j = this.childs[z].tasks.findIndex((t) => t.id === parsed.tid);
j !== -1 && this.childs[z].tasks[j].res[parsed.call](...parsed.args);
break;
case types_1.ChildCmd.next:
let index = this.childs[z].tasks.findIndex((t) => t.id === parsed.tid);
let next = (index !== -1 && this.childs[z].tasks.splice(index, 1).at(0)?.next);
parsed.arg !== undefined && next && next(parsed.arg);
break;
default:
throw new Error(`Unknown command : '${parsed.cmd}'`);
}
});
child.on(strings_1.error, (e) => {
console.error(e);
if (config_1.default.restartThreads)
return this.newChild();
else
throw e;
});
config_1.default.debug && console.debug("Creating child id ", this.inc, " :\nsources :", this._sources);
(0, postMessage_1.postChild)(child, {
cmd: types_1.ParentCmd.setSource,
source: this._sources
});
this.childs.push({
id: this.inc,
instance: child,
tasks: [],
ready: false
});
}
;
dispatchTask(task) {
const occupation = [];
for (let i = 0; i < this.childs.length; i++) {
const child = this.childs[i];
child.ready ? occupation.push(child.tasks.length) : occupation.push(Infinity);
}
const min = Math.min(...occupation);
const i = occupation.indexOf(min);
this.childs[i].tasks.push(task);
occupation[i]++;
(0, postMessage_1.postChild)(this.childs[i].instance, {
cmd: types_1.ParentCmd.request,
req: config_1.default.cleanRequest(task.req),
id: task.id
});
}
;
addSource(source) {
for (let i = 0; i < source.length; i++) {
this._sources.push({
path: source[i],
type: types_1.SourceType.CONTROLLER
});
}
this.postChilds(types_1.ParentCmd.setSource, {
source: this._sources
});
}
;
addMiddleware(path, opts) {
this._sources.push({
path,
type: types_1.SourceType.GLOBAL_MIDDLEWARE,
args: opts
});
this.postChilds(types_1.ParentCmd.setSource, {
source: this._sources
});
}
;
removeMiddleware(opts, path) {
if (!path) {
this._sources = this._sources.filter((source) => source.type !== types_1.SourceType.GLOBAL_MIDDLEWARE);
}
else {
for (let i = 0; i < this._sources.length; i++) {
if (this._sources[i].type !== types_1.SourceType.GLOBAL_MIDDLEWARE)
continue;
if (this._sources[i].path === path && (0, compareArray_1.compareArray)(this._sources[i].args ?? [], opts))
this._sources.splice(i, 1);
}
}
this.postChilds(types_1.ParentCmd.setSource, {
source: this._sources
});
}
;
close() {
for (let i = 0; i < this.childs.length; i++) {
this.childs[i].instance.terminate();
}
}
;
postChilds(cmd, data) {
data.cmd = cmd;
for (let i = 0; i < this.childs.length; i++) {
(0, postMessage_1.postChild)(this.childs[i].instance, data);
}
}
;
get _sourcesList() {
return this._sources;
}
;
get _inc() {
return this.inc;
}
}
exports.Instance = worker_threads_1.isMainThread ? new Parent() : null;
exports.default = exports.Instance;
//# sourceMappingURL=Parent.js.map