@arrows/worker
Version:
Simple, promise-based API for native worker threads (with pools)
59 lines (58 loc) • 2.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const worker_threads_1 = require("worker_threads");
const os_1 = require("os");
const defaultConfig = {
poolSize: os_1.cpus().length,
};
/**
* Spawns a workers pool from worker defined in a separate file,
* returns a function that handles messaging and returns responses as promises.
*
* Use when you want to separate worker definition from spawning a thread pool.
*
* @param fileName Path to a worker definition file created with `work` function
* @param config Configuration options
* @returns Async function that communicates with worker threads
*/
const spawn = (fileName, config = {}) => {
const cfg = { ...defaultConfig, ...config };
const { poolSize, transfer, ...options } = cfg;
if (poolSize <= 0) {
throw new Error("Pool size has to be > 0");
}
const promises = new Map();
const workers = Array.from({ length: poolSize }, () => new worker_threads_1.Worker(fileName, options).on("message", ([id, data, error]) => {
if (error) {
promises.get(id).reject(error);
}
else {
promises.get(id).resolve(data);
}
promises.delete(id);
}));
let workerIndex = 0;
const fn = (payload, transferList) => {
const id = process.hrtime.bigint();
const promise = new Promise((resolve, reject) => {
promises.set(id, { resolve, reject });
});
workers[workerIndex].postMessage([id, payload], transferList);
workerIndex = (workerIndex + 1) % poolSize;
return promise;
};
const task = Object.assign(fn, {
ref() {
workers.forEach((worker) => worker.ref());
},
unref() {
workers.forEach((worker) => worker.unref());
},
terminate() {
return Promise.all(workers.map((worker) => worker.terminate()));
},
});
return task;
};
exports.spawn = spawn;
exports.default = spawn;