UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

104 lines (103 loc) 3.64 kB
import { Worker } from "node:worker_threads"; import { cpus } from "node:os"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const __filename = fileURLToPath(import.meta.url), __dirname = dirname(__filename); class BuildWorkerPool { workers = []; available = []; taskQueue = []; pendingById = /* @__PURE__ */ new Map(); nextId = 0; readyCount = 0; initCount = 0; _ready; _resolveReady; _initialized; _resolveInitialized; _terminated = !1; constructor(size = Math.max(1, cpus().length - 1)) { this._ready = new Promise((resolve) => { this._resolveReady = resolve; }), this._initialized = new Promise((resolve) => { this._resolveInitialized = resolve; }); const workerPath = join(__dirname, "buildPageWorker.mjs"); for (let i = 0; i < size; i++) { const worker = new Worker(workerPath); worker.on("message", (msg) => { if (msg.type === "ready") this.readyCount++, this.available.push(worker), this.readyCount === size && this._resolveReady(); else if (msg.type === "init-done") this.initCount++, this.initCount === size && this._resolveInitialized(), this.dispatch(); else if (msg.type === "done" || msg.type === "error") { const pending = this.pendingById.get(msg.id); pending && (this.pendingById.delete(msg.id), msg.type === "done" ? pending.resolve(msg.result) : pending.reject(new Error(msg.error))), this.available.push(worker), this.dispatch(); } }), worker.on("error", (err) => { console.error("[BuildWorkerPool] Worker error:", err); }), this.workers.push(worker); } } get size() { return this.workers.length; } // initialize all workers - they load config themselves from vite.config async initialize() { await this._ready; for (const worker of this.workers) worker.postMessage({ type: "init", id: this.nextId++ }); await this._initialized; } dispatch() { for (; this.available.length > 0 && this.taskQueue.length > 0; ) { const worker = this.available.shift(), { msg, pending } = this.taskQueue.shift(); this.pendingById.set(pending.id, pending), worker.postMessage(msg); } } async buildPage(args) { if (this._terminated) throw new Error("Worker pool has been terminated"); const serializedRoute = { type: args.foundRoute.type, file: args.foundRoute.file, // only keep serializable layout data layouts: args.foundRoute.layouts?.map((layout) => ({ contextKey: layout.contextKey, loaderServerPath: layout.loaderServerPath, layoutRenderMode: layout.layoutRenderMode })), // only keep contextKey from middlewares middlewares: args.foundRoute.middlewares?.map((mw) => ({ contextKey: mw.contextKey })) }, id = this.nextId++, msg = { type: "build", id, args: { ...args, foundRoute: serializedRoute } }; return new Promise((resolve, reject) => { const pending = { id, resolve, reject }; this.taskQueue.push({ msg, pending }), this.dispatch(); }); } async terminate() { this._terminated = !0, await Promise.all(this.workers.map((w) => w.terminate())), this.workers = [], this.available = []; } } let pool = null; function getWorkerPool(size) { return pool || (pool = new BuildWorkerPool(size)), pool; } async function terminateWorkerPool() { pool && (await pool.terminate(), pool = null); } export { BuildWorkerPool, getWorkerPool, terminateWorkerPool }; //# sourceMappingURL=workerPool.js.map