UNPKG

@tripod311/leg5

Version:

Zero-dependency concurrent function execution for Node.js using worker threads.

102 lines (101 loc) 3.45 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const worker_threads_1 = require("worker_threads"); const path_1 = __importDefault(require("path")); const tools_1 = require("./tools"); class Thread { constructor(id, abort_timeout, onRelease) { this.known_tasks = new Set(); this.currentTask = null; this.id = id; this.abort_timeout = abort_timeout; this.onRelease = onRelease; this.create_worker(); } shutdown() { this.worker.postMessage({ command: "terminate" }); this.timeout = setTimeout(() => { this.worker.terminate(); }, this.abort_timeout); } create_worker() { this.known_tasks.clear(); const workerPath = path_1.default.join(__dirname, 'executor.js'); this.worker = new worker_threads_1.Worker(workerPath); this.worker.on("message", this.handle_message.bind(this)); this.worker.on("error", this.handle_error.bind(this)); } run(task) { this.currentTask = task; this.currentTask.assign(this.abort.bind(this)); const transferlist = (0, tools_1.get_transferlist)(task.args); if (this.known_tasks.has(this.currentTask.name)) { this.worker.postMessage({ command: "execute", name: this.currentTask.name, args: this.currentTask.args, timeout: this.currentTask.timeout }, transferlist); } else { this.known_tasks.add(this.currentTask.name); this.worker.postMessage({ command: "execute", name: this.currentTask.name, script: this.currentTask.script, argsList: this.currentTask.argsList, args: this.currentTask.args, timeout: this.currentTask.timeout }, transferlist); } } abort() { this.worker.postMessage({ command: "abort" }); this.timeout = setTimeout(this.forceAbort.bind(this), this.abort_timeout); } handle_message(message) { clearTimeout(this.timeout); switch (message.command) { case "finished": this.currentTask?.finish(message.payload); this.currentTask = null; this.onRelease(this.id); break; case "failed": this.currentTask?.fail(message.error.message); this.currentTask = null; this.onRelease(this.id); break; case "aborted": this.currentTask?.fail(new Error("Aborted")); this.currentTask = null; this.onRelease(this.id); break; } } handle_error(err) { this.currentTask?.fail(err); this.currentTask = null; this.onRelease(this.id); this.create_worker(); } forceAbort() { this.worker.terminate(); this.currentTask?.fail(new Error("Worker terminated")); this.create_worker(); } forget_task(name) { this.known_tasks.delete(name); } get isBusy() { return this.currentTask !== null; } } exports.default = Thread;