Add missed file.
[e-mobility-charging-stations-simulator.git] / src / worker / WorkerSet.ts
CommitLineData
6013bc53
JB
1import Constants from '../utils/Constants';
2import Utils from '../utils/Utils';
3import { Worker } from 'worker_threads';
4import WorkerData from '../types/WorkerData';
3e1416d8 5import { WorkerEvents } from '../types/WorkerEvents';
144cabe0 6import Wrk from './Wrk';
6013bc53
JB
7
8export default class WorkerSet extends Wrk {
9 public maxElementsPerWorker: number;
10 private workers: Set<Worker>;
11 private lastWorkerNumberOfElements: number;
12
13 /**
14 * Create a new `WorkerSet`.
15 *
16 * @param {string} workerScript
17 * @param {number} maxElementsPerWorker
18 */
19 constructor(workerScript: string, maxElementsPerWorker = 1) {
20 super(workerScript);
21 this.workers = new Set<Worker>();
22 this.maxElementsPerWorker = maxElementsPerWorker;
23 this.lastWorkerNumberOfElements = 0;
24 }
25
26 get size(): number {
27 return this.workers.size;
28 }
29
30 /**
31 *
32 * @return {Promise<void>}
33 * @public
34 */
35 public async addElement(elementData: WorkerData): Promise<void> {
36 if (!this.workers) {
37 throw Error('Cannot add a WorkerSet element: workers set does not exist');
38 }
39 if (this.lastWorkerNumberOfElements >= this.maxElementsPerWorker) {
40 void this.startWorker();
41 this.lastWorkerNumberOfElements = 0;
42 // Start worker sequentially to optimize memory at startup
43 void Utils.sleep(Constants.START_WORKER_DELAY);
44 }
3e1416d8 45 this.getLastWorker().postMessage({ id: WorkerEvents.START_WORKER_ELEMENT, workerData: elementData });
6013bc53
JB
46 this.lastWorkerNumberOfElements++;
47 }
48
49 /**
50 *
51 * @return {Promise<void>}
52 * @public
53 */
54 public async start(): Promise<void> {
55 await this.startWorker();
56 // Start worker sequentially to optimize memory at startup
57 await Utils.sleep(Constants.START_WORKER_DELAY);
58 }
59
60 /**
61 *
62 * @return {Promise}
63 * @private
64 */
65 private async startWorker() {
66 return new Promise((resolve, reject) => {
67 const worker = new Worker(this.workerScript);
68 worker.on('message', resolve);
69 worker.on('error', reject);
70 worker.on('exit', (code) => {
71 if (code !== 0) {
72 reject(new Error(`Worker stopped with exit code ${code}`));
73 }
74 });
75 this.workers.add(worker);
76 });
77 }
78
79 private getLastWorker(): Worker {
80 let worker: Worker;
81 // eslint-disable-next-line no-empty
82 for (worker of this.workers) { }
83 return worker;
84 }
85}