File: /volume1/@appstore/Spreadsheet/server/common/thread-worker-pool/index.js
"use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"ThreadWorkerPool",{enumerable:true,get:function(){return a}});const e=require("./linked-list");const r=require("@synology-office/thread-worker");const t=require("./task");const o=require("worker_threads");const s=require("@synology-office/task-queue");const i=u(require("path"));function n(e){if(typeof WeakMap!=="function")return null;var r=new WeakMap;var t=new WeakMap;return(n=function(e){return e?t:r})(e)}function u(e,r){if(!r&&e&&e.__esModule){return e}if(e===null||typeof e!=="object"&&typeof e!=="function"){return{default:e}}var t=n(r);if(t&&t.has(e)){return t.get(e)}var o={__proto__:null};var s=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e){if(i!=="default"&&Object.prototype.hasOwnProperty.call(e,i)){var u=s?Object.getOwnPropertyDescriptor(e,i):null;if(u&&(u.get||u.set)){Object.defineProperty(o,i,u)}else{o[i]=e[i]}}}o.default=e;if(t){t.set(e,o)}return o}class k extends e.ListNode{constructor(e){super();this.worker=e;this.reuseCount=0}getWorker(){return this.worker}incReuseCounter(){this.reuseCount++}getReuseCount(){return this.reuseCount}}class a extends r.ThreadWorkerManager{constructor({module:r,minWorker:t,maxWorker:o,endurance:i,reduceWorkerDelay:n}){super();this.callQueue=new s.TaskQueue({concurrency:o});this.module=r;this.minWorker=t;this.maxWorker=o;this.endurance=i||Infinity;this.reduceWorkerDelay=n===undefined?2e4:n;this.busyWorkers=new e.LinkedList;this.freeWorkers=new e.LinkedList;this.keepMinWorker()}createWorker(){return new o.Worker(i.join(__dirname,"worker.js"),{workerData:{module:this.module}})}createWorkerTask(e,r,o){return new t.WorkerTask(e,r,o)}acquireWorker(){const e=this.createWorker();this.freeWorkers.insertFront(new k(e));this.addWorker(e)}onWorkerExit(e,r){const t=this.freeWorkers.find((r=>r.getWorker()===e));if(t){this.freeWorkers.remove(t)}super.onWorkerExit(e,r)}callFunction(e,r=[],{description:t,timeout:o}={}){return this.callQueue.enqueue(this.consume.bind(this),{arg:{method:e,args:r,description:t,timeout:o}})}consume(e){if(this.freeWorkers.getSize()===0){this.acquireWorker()}const r=this.freeWorkers.shift();if(!r){return Promise.reject("worker-pool: can not get free worker")}this.busyWorkers.insertFront(r);r.incReuseCounter();return this.executeWorkerTask(r.getWorker(),{cmd:"callFunction",data:{method:e.method,args:e.args}},{timeout:e.timeout,description:e.description}).then((e=>e.data)).finally((()=>this.onTaskDone(r)))}onTaskDone(e){this.busyWorkers.remove(e);if(e.getReuseCount()<this.endurance){this.freeWorkers.insertFront(e)}else{this.removeWorker(e.getWorker())}this.keepMinWorker();if(this.callQueue.isEmpty()&&this.reduceWorkerDelay>0){setTimeout((()=>this.removeSpareWorkers()),this.reduceWorkerDelay)}}keepMinWorker(){const e=this.busyWorkers.getSize();while(e+this.freeWorkers.getSize()<this.minWorker){this.acquireWorker()}}removeSpareWorkers(){if(!this.callQueue.isEmpty()){return}while(this.freeWorkers.getSize()>this.minWorker){const e=this.freeWorkers.shift();if(e){this.removeWorker(e.getWorker())}}}stat(){const e=[];this.busyWorkers.forEach((r=>{const t=this.getTaskMap(r.getWorker());if(!t){return}for(const r of t.values()){e.push(r.getDescription()||"")}}));return{free_workers_count:this.freeWorkers.getSize(),running_tasks:e}}destroy(){const e=e=>{while(e.getSize()>0){const r=e.shift();if(r){this.removeWorker(r.getWorker())}}};e(this.busyWorkers);e(this.freeWorkers)}}