1 import { WorkerEvents
, WorkerSetElement
} from
'../types/Worker';
3 import Utils from
'../utils/Utils';
4 import { Worker
} from
'worker_threads';
5 import WorkerAbstract from
'./WorkerAbstract';
7 export default class WorkerSet
<T
> extends WorkerAbstract
{
8 public maxElementsPerWorker
: number;
9 private workerSet
: Set
<WorkerSetElement
>;
12 * Create a new `WorkerSet`.
14 * @param {string} workerScript
15 * @param {number} maxElementsPerWorker
16 * @param {number} workerStartDelay
18 constructor(workerScript
: string, maxElementsPerWorker
= 1, workerStartDelay
?: number) {
19 super(workerScript
, workerStartDelay
);
20 this.workerSet
= new Set
<WorkerSetElement
>();
21 this.maxElementsPerWorker
= maxElementsPerWorker
;
25 return this.workerSet
.size
;
31 * @returns {Promise<void>}
34 public async addElement(elementData
: T
): Promise
<void> {
35 if (!this.workerSet
) {
36 throw Error('Cannot add a WorkerSet element: workers\' set does not exist');
38 if (this.getLastWorkerSetElement().numberOfWorkerElements
>= this.maxElementsPerWorker
) {
40 // Start worker sequentially to optimize memory at startup
41 await Utils
.sleep(this.workerStartDelay
);
43 this.getLastWorker().postMessage({ id
: WorkerEvents
.START_WORKER_ELEMENT
, workerData
: elementData
});
44 this.getLastWorkerSetElement().numberOfWorkerElements
++;
49 * @returns {Promise<void>}
52 public async start(): Promise
<void> {
54 // Start worker sequentially to optimize memory at startup
55 await Utils
.sleep(this.workerStartDelay
);
60 * @returns {Promise<void>}
63 public async stop(): Promise
<void> {
64 for (const workerSetElement
of this.workerSet
) {
65 await workerSetElement
.worker
.terminate();
67 this.workerSet
.clear();
74 private startWorker(): void {
75 const worker
= new Worker(this.workerScript
);
76 worker
.on('message', () => { });
77 worker
.on('error', () => { });
78 worker
.on('exit', (code
) => {
80 console
.error(`Worker stopped with exit code ${code}`);
82 this.workerSet
.delete(this.getWorkerSetElementByWorker(worker
));
84 this.workerSet
.add({ worker
, numberOfWorkerElements
: 0 });
87 private getLastWorkerSetElement(): WorkerSetElement
{
88 let workerSetElement
: WorkerSetElement
;
89 // eslint-disable-next-line no-empty
90 for (workerSetElement
of this.workerSet
) { }
91 return workerSetElement
;
94 private getLastWorker(): Worker
{
95 return this.getLastWorkerSetElement().worker
;
98 private getWorkerSetElementByWorker(worker
: Worker
): WorkerSetElement
{
99 let workerSetElt
: WorkerSetElement
;
100 this.workerSet
.forEach((workerSetElement
) => {
101 if (workerSetElement
.worker
.threadId
=== worker
.threadId
) {
102 workerSetElt
= workerSetElement
;