module.exports = () => { const workers = {}; const runningWorkers = {}; let jobQueue = []; const dequeue = () => { if (jobQueue.length !== 0) { const wIds = Object.keys(workers); for (let i = 0; i < wIds.length; i += 1) { if (typeof runningWorkers[wIds[i]] === 'undefined') { jobQueue[0](workers[wIds[i]]); break; } } } }; const queue = (action, payload) => ( new Promise((resolve, reject) => { jobQueue.push(async (w) => { jobQueue.shift(); runningWorkers[w.id] = true; try { resolve(await w[action].apply(this, payload)); } catch (err) { reject(err); } finally { delete runningWorkers[w.id]; dequeue(); } }); dequeue(); }) ); const addWorker = (w) => { workers[w.id] = w; return w.id; }; const addJob = (action, ...payload) => ( queue(action, payload) ); const terminate = async () => { Object.keys(workers).forEach(async (id) => { await workers[id].terminate(); }); jobQueue = []; }; return { addWorker, addJob, terminate, }; };