1 import Constants from
'../utils/Constants';
2 import Utils from
'../utils/Utils';
3 import { Worker
} from
'worker_threads';
4 import WorkerData from
'../types/WorkerData';
5 import Wrk from
'./Worker';
7 export default class WorkerSet
extends Wrk
{
8 public maxElementsPerWorker
: number;
9 private workers
: Set
<Worker
>;
10 private lastWorkerNumberOfElements
: number;
13 * Create a new `WorkerSet`.
15 * @param {string} workerScript
16 * @param {number} maxElementsPerWorker
18 constructor(workerScript
: string, maxElementsPerWorker
= 1) {
20 this.workers
= new Set
<Worker
>();
21 this.maxElementsPerWorker
= maxElementsPerWorker
;
22 this.lastWorkerNumberOfElements
= 0;
26 return this.workers
.size
;
31 * @return {Promise<void>}
34 public async addElement(elementData
: WorkerData
): Promise
<void> {
36 throw Error('Cannot add a WorkerSet element: workers set does not exist');
38 if (this.lastWorkerNumberOfElements
>= this.maxElementsPerWorker
) {
39 void this.startWorker();
40 this.lastWorkerNumberOfElements
= 0;
41 // Start worker sequentially to optimize memory at startup
42 void Utils
.sleep(Constants
.START_WORKER_DELAY
);
44 this.getLastWorker().postMessage({ id
: Constants
.START_WORKER_ELEMENT
, workerData
: elementData
});
45 this.lastWorkerNumberOfElements
++;
50 * @return {Promise<void>}
53 public async start(): Promise
<void> {
54 await this.startWorker();
55 // Start worker sequentially to optimize memory at startup
56 await Utils
.sleep(Constants
.START_WORKER_DELAY
);
64 private async startWorker() {
65 return new Promise((resolve
, reject
) => {
66 const worker
= new Worker(this.workerScript
);
67 worker
.on('message', resolve
);
68 worker
.on('error', reject
);
69 worker
.on('exit', (code
) => {
71 reject(new Error(`Worker stopped with exit code ${code}`));
74 this.workers
.add(worker
);
78 private getLastWorker(): Worker
{
80 // eslint-disable-next-line no-empty
81 for (worker
of this.workers
) { }