-// Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
-
-import { ChargingStationWorkerData, ChargingStationWorkerMessage, ChargingStationWorkerMessageEvents } from '../types/ChargingStationWorker';
-
-import Configuration from '../utils/Configuration';
-import Statistics from '../types/Statistics';
-import { Storage } from '../performance/storage/Storage';
-import { StorageFactory } from '../performance/storage/StorageFactory';
-import { UIServiceUtils } from './ui-websocket-services/UIServiceUtils';
-import UIWebSocketServer from './UIWebSocketServer';
-import Utils from '../utils/Utils';
-import WorkerAbstract from '../worker/WorkerAbstract';
-import WorkerFactory from '../worker/WorkerFactory';
-import chalk from 'chalk';
-import { isMainThread } from 'worker_threads';
-import path from 'path';
-import { version } from '../../package.json';
-
-export default class Bootstrap {
- private static instance: Bootstrap | null = null;
- private workerImplementation: WorkerAbstract<ChargingStationWorkerData> | null = null;
- private readonly uiWebSocketServer!: UIWebSocketServer;
- private readonly storage!: Storage;
- private numberOfChargingStations: number;
- private readonly version: string = version;
- private started: boolean;
- private readonly workerScript: string;
-
- private constructor() {
- this.started = false;
- this.workerScript = path.join(path.resolve(__dirname, '../'), 'charging-station', 'ChargingStationWorker.js');
- this.initWorkerImplementation();
- Configuration.getUIWebSocketServer().enabled && (this.uiWebSocketServer = new UIWebSocketServer({
- ...Configuration.getUIWebSocketServer().options, handleProtocols: UIServiceUtils.handleProtocols
- }));
- Configuration.getPerformanceStorage().enabled && (this.storage = StorageFactory.getStorage(
- Configuration.getPerformanceStorage().type,
- Configuration.getPerformanceStorage().uri,
- this.logPrefix()
- ));
- Configuration.setConfigurationChangeCallback(async () => Bootstrap.getInstance().restart());
- }
-
- public static getInstance(): Bootstrap {
- if (!Bootstrap.instance) {
- Bootstrap.instance = new Bootstrap();
+// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+
+import { EventEmitter } from 'node:events'
+import { dirname, extname, join } from 'node:path'
+import process, { exit } from 'node:process'
+import { fileURLToPath } from 'node:url'
+
+import chalk from 'chalk'
+import { availableParallelism } from 'poolifier'
+
+import { waitChargingStationEvents } from './Helpers.js'
+import type { AbstractUIServer } from './ui-server/AbstractUIServer.js'
+import { UIServerFactory } from './ui-server/UIServerFactory.js'
+import { version } from '../../package.json'
+import { BaseError } from '../exception/index.js'
+import { type Storage, StorageFactory } from '../performance/index.js'
+import {
+ type ChargingStationData,
+ type ChargingStationWorkerData,
+ type ChargingStationWorkerMessage,
+ type ChargingStationWorkerMessageData,
+ ChargingStationWorkerMessageEvents,
+ ConfigurationSection,
+ ProcedureName,
+ type StationTemplateUrl,
+ type Statistics,
+ type StorageConfiguration,
+ type UIServerConfiguration,
+ type WorkerConfiguration
+} from '../types/index.js'
+import {
+ Configuration,
+ Constants,
+ formatDurationMilliSeconds,
+ generateUUID,
+ handleUncaughtException,
+ handleUnhandledRejection,
+ isNotEmptyArray,
+ logPrefix,
+ logger
+} from '../utils/index.js'
+import { type WorkerAbstract, WorkerFactory } from '../worker/index.js'
+
+const moduleName = 'Bootstrap'
+
+enum exitCodes {
+ succeeded = 0,
+ missingChargingStationsConfiguration = 1,
+ noChargingStationTemplates = 2,
+ gracefulShutdownError = 3,
+}
+
+export class Bootstrap extends EventEmitter {
+ private static instance: Bootstrap | null = null
+ public numberOfChargingStations!: number
+ public numberOfChargingStationTemplates!: number
+ private workerImplementation?: WorkerAbstract<ChargingStationWorkerData>
+ private readonly uiServer?: AbstractUIServer
+ private storage?: Storage
+ private numberOfStartedChargingStations!: number
+ private readonly version: string = version
+ private initializedCounters: boolean
+ private started: boolean
+ private starting: boolean
+ private stopping: boolean
+
+ private constructor () {
+ super()
+ for (const signal of ['SIGINT', 'SIGQUIT', 'SIGTERM']) {
+ process.on(signal, this.gracefulShutdown.bind(this))
+ }
+ // Enable unconditionally for now
+ handleUnhandledRejection()
+ handleUncaughtException()
+ this.started = false
+ this.starting = false
+ this.stopping = false
+ this.initializedCounters = false
+ this.initializeCounters()
+ this.uiServer = UIServerFactory.getUIServerImplementation(
+ Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
+ )
+ Configuration.configurationChangeCallback = async () => {
+ await Bootstrap.getInstance().restart(false)
+ }
+ }
+
+ public static getInstance (): Bootstrap {
+ if (Bootstrap.instance === null) {
+ Bootstrap.instance = new Bootstrap()