@ywfe/cli
Version:
遥望前端开发命令行工具
73 lines (72 loc) • 2.44 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const node_async_hooks_1 = require("node:async_hooks");
const node_events_1 = require("node:events");
const node_worker_threads_1 = require("node:worker_threads");
const path = require("path");
const kTaskInfo = Symbol('kTaskInfo');
const kWorkerFreedEvent = Symbol('kWorkerFreedEvent');
class WorkerPoolTaskInfo extends node_async_hooks_1.AsyncResource {
constructor(callback) {
super('WorkerPoolTaskInfo');
this.callback = callback;
}
done(err, result) {
this.runInAsyncScope(this.callback, null, err, result);
this.emitDestroy();
}
}
class WorkerPool extends node_events_1.EventEmitter {
constructor(numThreads) {
super();
this.numThreads = numThreads;
this.workers = [];
this.freeWorkers = [];
this.tasks = [];
for (let i = 0; i < numThreads; i++) {
this.addNewWorker();
}
this.on(kWorkerFreedEvent, () => {
if (this.tasks.length > 0) {
const { pageName, callback } = this.tasks.shift();
this.runTask(pageName, callback);
}
});
}
addNewWorker() {
const worker = new node_worker_threads_1.Worker(path.resolve(__dirname, 'task-processor.js'));
worker.on('message', (result) => {
worker[kTaskInfo].done(null, result);
worker[kTaskInfo] = null;
this.freeWorkers.push(worker);
this.emit(kWorkerFreedEvent);
});
worker.on('error', (err) => {
if (worker[kTaskInfo]) {
worker[kTaskInfo].done(err, null);
}
else {
this.emit('error', err);
}
this.workers.splice(this.workers.indexOf(worker), 1);
this.addNewWorker();
});
this.workers.push(worker);
this.freeWorkers.push(worker);
this.emit(kWorkerFreedEvent);
}
runTask(pageName, callback) {
if (this.freeWorkers.length === 0) {
this.tasks.push({ pageName, callback });
return;
}
const worker = this.freeWorkers.pop();
worker[kTaskInfo] = new WorkerPoolTaskInfo(callback);
worker.postMessage(pageName);
}
close() {
for (const worker of this.workers)
worker.terminate();
}
}
exports.default = WorkerPool;