nanolith
Version:
Multi-threading in no time with seamless TypeScript support.
1 lines • 2.1 kB
JavaScript
import{randomUUID as v4}from"crypto";import{TypedEmitter}from"tiny-typed-emitter";import{listenForStream,prepareWritableToPortStream}from"../streams/index.js";export class Service extends TypedEmitter{#e;#t=!1;#r=0;#s=new Map;constructor(e){super(),this.#e=e;const t=e=>{if(8===e.type)return this.#s.forEach((({resolve:t,reject:r})=>{const{code:s}=e;return 0!==s?r(new Error(`Worker exited early with code ${s}!`)):t(void 0)}));const t=e.key;if(!t)return;const{resolve:r,reject:s}=this.#s.get(t);switch(e.type){case 3:r(e.data);break;case 4:s(e.data);break;default:return}};this.#e.on("message",t),this.#e.once("exit",(r=>{this.#t=!0,this.#s.clear(),this.emit("terminated",r),e.off("message",t)}))}get activeCalls(){return this.#r}get closed(){return this.#t}get worker(){return this.#e}#a(){if(this.#t)throw new Error("Attempting to execute operations on a service with an exited process!")}async call({name:e,params:t,transferList:r}){this.#a(),this.#r++;const s=v4(),a={type:1,name:e,params:t??[],key:s},i=new Promise(((e,t)=>{const r=this.#i({key:s,resolve:t=>{e(t),r()},reject:t})}));return this.#e.postMessage(a,r),i.finally((()=>this.#r--))}#i({key:e,...t}){return this.#s.set(e,t),()=>{this.#s.delete(e)}}setRef(e){if(e)return this.#e.ref();this.#e.unref()}async close(e){this.#t=!0,this.#e.emit("exit",e??0),this.#s.clear(),await this.#e.terminate()}sendMessage(e,t){this.#a();const r={type:0,data:e};this.#e.postMessage(r,t)}createStream(e){return this.#a(),prepareWritableToPortStream(this.#e,e??{})}onStream(e){return this.#a(),listenForStream(this.#e,e)}onMessage(e){this.#a();const t=async t=>{0===t.type&&await e(t.data)};return this.#e.on("message",t),()=>this.#e.off("message",t)}async waitForMessage(e){return this.#a(),new Promise((t=>{const r=async s=>{if(0!==s.type)return;const{data:a}=s;e(a)&&(t(a),this.#e.off("message",r))};this.#e.on("message",r)}))}sendMessenger(e){this.#a();const t=e.raw,r={type:3,data:t},s=new Promise((e=>{const r=s=>{5===s.type&&s.data===t.__messengerID&&(e(void 0),this.#e.off("message",r))};this.#e.on("message",r)}));return this.#e.postMessage(r),s}}