UNPKG

@pouchlab/worker-pool

Version:

A worker pool for bun,nodejs,browser,deno..run cpu intensive tasks in parallel

70 lines (69 loc) 5.3 kB
import{createRequire as X}from"node:module";var O=Object.create;var{getPrototypeOf:Q,defineProperty:H,getOwnPropertyNames:S}=Object;var T=Object.prototype.hasOwnProperty;var V=(x,z,P)=>{P=x!=null?O(Q(x)):{};let A=z||!x||!x.__esModule?H(P,"default",{value:x,enumerable:!0}):P;for(let C of S(x))if(!T.call(A,C))H(A,C,{get:()=>x[C],enumerable:!0});return A};var Y=X(import.meta.url);var K=await async function(){return(await import("node:worker_threads")||Worker).Worker}();import{Json as Z,checktype as M,genListByRange as $}from"@pouchlab/core-utils";import I from"eventemitter3";function L(){var x=` //define self on nodejs void !function () { typeof self == 'undefined' && typeof global == 'object' && (global.self = global); }(); import EventEmitter from "eventemitter3"; import { Json } from "@pouchlab/core-utils"; var QueueEmitter = new EventEmitter; var ctx = self; var jobs_count = 0; async function scheduleJob(job) { try { let func = job.fn; if (func && func.then || func.catch || func instanceof Promise) { const completed = await func.call(this); jobs_count = jobs_count - 1; ctx.postMessage({ msg: "count", num: jobs_count, wrk_id: job?.wrkid }); let timmer = setTimeout(() => { ctx.postMessage({ iserror: false, msg: completed?.status || "completed", error: null, data: completed || null, id: job.id }); clearTimeout(timmer); }, job.delay || 0); } else { let data = await func(); jobs_count = jobs_count - 1; ctx.postMessage({ msg: "count", num: jobs_count, wrk_id: job?.wrkid }); let timmer = setTimeout(() => { ctx.postMessage({ iserror: false, msg: data?.status || "completed", error: null, data: data || null, id: job.id }); clearTimeout(timmer); }, job.delay || 0); } } catch (error) { jobs_count = jobs_count - 1; ctx.postMessage({ msg: "count", num: jobs_count }); ctx.postMessage({ iserror: true, msg: "error occurred", error, data: null, id: job.id }); } } QueueEmitter.on("scheduled_job", scheduleJob); ctx.onmessage = async (msg) => { let j = Json.parse(msg.data); ctx.postMessage({ data: { status: "running", id: j.id, fn: j.fn.toString() } }); jobs_count = jobs_count + 1; ctx.postMessage({ msg: "count", num: jobs_count, wrk_id: j?.wrkid }); QueueEmitter.emit("scheduled_job", j); }; var worker_default = ctx; export { worker_default as default }; `,z;try{return z=new Blob([x],{type:"application/javascript"}),new URL("./worker.js",import.meta.url)||URL?.createObjectURL(z)}catch(P){return new URL("./worker.js",import.meta.url)}}function R(x,...z){if(x&&typeof x==="number"&&x<=50){let P=[];for(let A=0;A<=x;A++){let C=new K(L());P.push({id:crypto.randomUUID(),worker:C,isActive:!1})}if(P=z.concat(P),P&&P.length>0)return P;return P}}function U(x,z){for(let P of z)P.fn=P.fn,P.wrkid=x.id,x.worker.postMessage(Z.stringify(P)),x.isActive=!0}async function B(x,z){x=Array.from(x.values()).filter((D)=>D.status==="stopped");let P=z?.filter((D)=>D?.isActive===!1),A=Math.floor(P?.length/2+2),C=await $(x,0,A),G=P?.sort().slice(0,C.length);for(let D in G){let N=G[D];U(N,C[D])}}class F{#A=new Map;#C=new Map;#D=new Map;#z;#x;#F;#P=new I;constructor(x={}){this.#z=new Map,this.#F=function(){if(Number(x?.numWorkers)<4)return 4;return Number(x?.numWorkers)}(),this.#x=R(this.#F,this.#x)||[],this.#x?.forEach((z)=>{z?.worker.on("error",(P)=>{if(this.#P.emit("worker_error",{id:z.id,error:P}),this.#x.length>0)this.#x=this.#x?.filter((A)=>A?.id!==z.id)}),z?.worker.on("message",(P)=>{if(P?.iserror){this.#P.emit("job_error",P);let A=this.#A.get(P?.id);if(!A)return;A.status="failed",this.#C.set(P?.id,A),this.#A.delete(P?.id)}if(P?.data?.status==="running"){let A=this.#z.get(P.data.id);if(!A)return;A.status="running",this.#z.set(P.data.id,A),this.#A.set(A.id,A),this.#P.emit("job_running",A)}if(P?.msg==="completed"){let A=this.#z.get(P.id);if(!A)return;A.status="completed",this.#D.set(P.id,A),this.#A.delete(A.id),this.#P.emit("job_completed",P)}if(P?.msg==="count")if(z.count=P?.num,z.count===0)z.isActive=!1;else if(z.count>=50)z.isActive=!0;else z.isActive=!1})}),this.#P.on("jobs_added",(z)=>{B(z,this.#x)})}addJob(x){if(!x||M(x)!==M({})||!x.fn||typeof x.fn!=="function"||x.delay&&typeof x.delay!=="number"||x.id&&typeof x.id!=="string")throw new Error("job must be a valid object && fn must be a function and is required");let z={id:x.id||crypto.randomUUID(),fn:x.fn,status:"stopped",delay:x.delay||0};if(this.#z.has(z.id))return;return this.#z.set(z.id,{id:z.id,fn:z.fn,status:z.status,delay:z.delay}),this.#P.emit("jobs_added",this.#z),this}async clear(){try{return this.#D.clear(),!0}catch(x){return!1}}runFailedJobs(){this.#C.forEach((x)=>{this.addJob(x)})}workers={list:async()=>{return this.#x},allActive:async()=>{return this.#x?.filter((x)=>x?.isActive===!0)},onError:(x)=>{if(x&&typeof x==="function")this.#P.on("worker_error",x);return this}};onCompleted(x){if(x&&typeof x==="function")this.#P.on("job_completed",(z)=>{return x(z)});return this}onError(x){if(x&&typeof x==="function")this.#P.on("job_error",x);return this}}var m=F;export{m as default,F as Pqueue};