/* COPYRIGHT Esri - https://js.arcgis.com/5.1.0/LICENSE.txt */
import{handlesGroup as t,makeHandle as o}from"../handleUtils.js";import"../has.js";import{createAbortError as e,isAborted as i,ignoreAbortErrors as s}from"../promiseUtils.js";import n from"../Queue.js";import{unregister as r}from"./connectionRegistry.js";import{createInvokeProxy as l}from"./InvokeHandler.js";import h from"./RemoteClient.js";class c{constructor(){this._clients=new Array,this._ongoingJobsQueue=new n,this._ongoingLowPriorityJobsQueue=new n,this._onClientConnectedCallbacks=new Set,this._clientOpenOptions=null,this._portSource=null,this._onClose=null,this._isProvisioningClient=!1,this._isClosed=!1}destroy(){this.close()}[Symbol.dispose](){this.destroy()}get closed(){return this._isClosed}async open(t,o,e){this._isClosed=!1,this._clientOpenOptions=o,this._portSource=t[Symbol.iterator](),this._onClose=e,this._clients.length=0,await this._tryAllocateNewClient()}broadcast(t,o,e){return this._clients.map(i=>i.invoke(t,o,e))}close(){if(this._isClosed)return;let t;for(this._isClosed=!0;t=this._ongoingJobsQueue.pop();)t.resolver.reject(e(`Worker closing, aborting job calling '${t.methodName}'`));for(;t=this._ongoingLowPriorityJobsQueue.pop();)t.resolver.reject(e(`Worker closing, aborting job calling '${t.methodName}'`));for(const o of this._clients)o.close();this._clients.length=0,this._onClose?.(),this._onClose=null,this._portSource?.return?.(),this._portSource=null,this._onClientConnectedCallbacks.clear(),r(this)}invoke(t,o,e){return this.apply(t,[o],e)}apply(t,o,e){const i=Promise.withResolvers();return(1===e?.jobPriority?this._ongoingLowPriorityJobsQueue:this._ongoingJobsQueue).push({methodName:t,data:o,invokeOptions:e,resolver:i}),this._provisionClientIfNeeded(),this._signalClientsJobAdded(),i.promise}createInvokeProxy(t){return l(this,t)}on(o,e){return t(this._clients.map(t=>t.on(o,e)))}onClientConnected(t){this._onClientConnectedCallbacks.add(t);for(const o of this._clients)o&&t(o);return o(()=>{this._onClientConnectedCallbacks.delete(t)})}openPorts(){return this._clients.map(t=>t.openPort())}get test(){}async _addClient(t,o){const s=await t;if(i(o)||this._isClosed)throw e();const n=new h(s,o,this._ongoingJobsQueue,this._ongoingLowPriorityJobsQueue);this._clients.push(n);for(const e of this._onClientConnectedCallbacks)e(n);n.jobAdded()}_signalClientsJobAdded(){for(const t of this._clients)t.jobAdded()}_provisionClientIfNeeded(){const t=this._ongoingJobsQueue.length>0||this._ongoingLowPriorityJobsQueue.length>0,o=this._clients.some(t=>t&&!t.isBusy());t&&!o&&s(this._tryAllocateNewClient())}async _tryAllocateNewClient(){const t=this._clientOpenOptions;if(!this._portSource||this._isClosed||!t||this._isProvisioningClient)return;const o=this._portSource.next();if(o.done)this._portSource=null;else{this._isProvisioningClient=!0;try{await this._addClient(o.value,t)}finally{this._isProvisioningClient=!1}}}}export{c as default};
