UNPKG

expressmultithread

Version:

Fast, light-weight and low dependency [Express.js](https://www.npmjs.com/package/express) multithreaded router.

175 lines 6.09 kB
"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"); const strings_2 = require("../constants/strings"); class Parent { constructor(threadCount = config_1.default.threadCount) { this.childs = []; this._sources = []; this.inc = 0; this.indexRobin = 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 task = this.childs[z].tasks.get(parsed.tid); task && task.res[parsed.call](...parsed.args); break; } case types_1.ChildCmd.next: { const task = this.childs[z].tasks.get(parsed.tid); if (task) { parsed.arg !== undefined && task.next(parsed.arg); this.childs[z].tasks.delete(parsed.tid); } 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: new Map(), ready: false }); } ; dispatchTask(task) { let i = 0; switch (config_1.default.dispatcher) { case strings_2.DispatcherType.ROUND_ROBIN: { i = (this.indexRobin++) % this.childs.length; break; } case strings_2.DispatcherType.LEAST_CONNECTION: { const occupation = this.childs.map((c) => c.ready ? c.tasks.size : Infinity); const min = Math.min(...occupation); i = occupation.indexOf(min); break; } default: { throw new Error(`Unknown dispatcher type: '${config_1.default.dispatcher}'`); } } this.childs[i].tasks.set(task.id, task); const cb = () => { task.res.removeListener("close", cb); task.res.removeListener("finish", cb); this.childs[i].tasks.delete(task.id); }; task.res.addListener("close", cb); task.res.addListener("finish", cb); (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