Update dependency.
[e-mobility-charging-stations-simulator.git] / src / worker / WorkerSet.ts
CommitLineData
8434025b 1import { WorkerEvents, WorkerSetElement } from '../types/Worker';
c045d9a9 2
6013bc53
JB
3import Constants from '../utils/Constants';
4import Utils from '../utils/Utils';
1e924543 5import { Worker } from 'worker_threads';
fd1fdf1b 6import WorkerAbstract from './WorkerAbstract';
6013bc53 7
fd1fdf1b 8export default class WorkerSet<T> extends WorkerAbstract {
6013bc53 9 public maxElementsPerWorker: number;
ded13d97 10 private workerSet: Set<WorkerSetElement>;
6013bc53
JB
11
12 /**
13 * Create a new `WorkerSet`.
14 *
15 * @param {string} workerScript
16 * @param {number} maxElementsPerWorker
17 */
18 constructor(workerScript: string, maxElementsPerWorker = 1) {
19 super(workerScript);
ded13d97 20 this.workerSet = new Set<WorkerSetElement>();
6013bc53 21 this.maxElementsPerWorker = maxElementsPerWorker;
6013bc53
JB
22 }
23
24 get size(): number {
ded13d97 25 return this.workerSet.size;
6013bc53
JB
26 }
27
28 /**
29 *
3340259a
JB
30 * @param elementData
31 * @returns {Promise<void>}
6013bc53
JB
32 * @public
33 */
8434025b 34 public async addElement(elementData: T): Promise<void> {
ded13d97 35 if (!this.workerSet) {
a4624c96 36 throw Error('Cannot add a WorkerSet element: workers\' set does not exist');
6013bc53 37 }
c045d9a9 38 if (this.getLastWorkerSetElement().numberOfWorkerElements >= this.maxElementsPerWorker) {
a4624c96 39 this.startWorker();
6013bc53 40 // Start worker sequentially to optimize memory at startup
a4624c96 41 await Utils.sleep(Constants.START_WORKER_DELAY);
6013bc53 42 }
3e1416d8 43 this.getLastWorker().postMessage({ id: WorkerEvents.START_WORKER_ELEMENT, workerData: elementData });
c045d9a9 44 this.getLastWorkerSetElement().numberOfWorkerElements++;
6013bc53
JB
45 }
46
47 /**
48 *
3340259a 49 * @returns {Promise<void>}
6013bc53
JB
50 * @public
51 */
52 public async start(): Promise<void> {
a4624c96 53 this.startWorker();
6013bc53
JB
54 // Start worker sequentially to optimize memory at startup
55 await Utils.sleep(Constants.START_WORKER_DELAY);
56 }
57
ded13d97
JB
58 /**
59 *
3340259a 60 * @returns {Promise<void>}
ded13d97
JB
61 * @public
62 */
63 public async stop(): Promise<void> {
64 for (const workerSetElement of this.workerSet) {
65 await workerSetElement.worker.terminate();
66 }
67 this.workerSet.clear();
68 }
69
6013bc53
JB
70 /**
71 *
6013bc53
JB
72 * @private
73 */
a4624c96
JB
74 private startWorker(): void {
75 const worker = new Worker(this.workerScript);
76 worker.on('message', () => { });
77 worker.on('error', () => { });
78 worker.on('exit', (code) => {
79 if (code !== 0) {
1e924543 80 console.error(`Worker stopped with exit code ${code}`);
a4624c96 81 }
d7a48614 82 this.workerSet.delete(this.getWorkerSetElementByWorker(worker));
6013bc53 83 });
ded13d97 84 this.workerSet.add({ worker, numberOfWorkerElements: 0 });
6013bc53
JB
85 }
86
c045d9a9
JB
87 private getLastWorkerSetElement(): WorkerSetElement {
88 let workerSetElement: WorkerSetElement;
6013bc53 89 // eslint-disable-next-line no-empty
ded13d97 90 for (workerSetElement of this.workerSet) { }
c045d9a9
JB
91 return workerSetElement;
92 }
93
94 private getLastWorker(): Worker {
95 return this.getLastWorkerSetElement().worker;
6013bc53 96 }
1e924543
JB
97
98 private getWorkerSetElementByWorker(worker: Worker): WorkerSetElement {
99 let workerSetElt: WorkerSetElement;
ded13d97 100 this.workerSet.forEach((workerSetElement) => {
1e924543
JB
101 if (JSON.stringify(workerSetElement.worker) === JSON.stringify(worker)) {
102 workerSetElt = workerSetElement;
103 }
104 });
105 return workerSetElt;
106 }
6013bc53 107}