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