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