From 6d2b7d0121fa6ab41272ed8f4f0d7fd2ce3e8c7d Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 27 Nov 2023 21:12:32 +0100 Subject: [PATCH] fix: fix performance configuration change at runtime MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/assets/config-template.json | 2 +- src/charging-station/Bootstrap.ts | 93 ++++++++++--------- .../ui-server/UIServerFactory.ts | 4 +- src/performance/storage/StorageFactory.ts | 8 +- src/worker/WorkerFactory.ts | 4 +- 5 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/assets/config-template.json b/src/assets/config-template.json index 6b06f2bf..5e18d942 100644 --- a/src/assets/config-template.json +++ b/src/assets/config-template.json @@ -11,7 +11,7 @@ "processType": "workerSet" }, "performanceStorage": { - "enabled": true, + "enabled": false, "type": "jsonfile" }, "uiServer": { diff --git a/src/charging-station/Bootstrap.ts b/src/charging-station/Bootstrap.ts index 003b093a..710d2c89 100644 --- a/src/charging-station/Bootstrap.ts +++ b/src/charging-station/Bootstrap.ts @@ -55,16 +55,16 @@ export class Bootstrap extends EventEmitter { private static instance: Bootstrap | null = null; public numberOfChargingStations!: number; public numberOfChargingStationTemplates!: number; - private workerImplementation: WorkerAbstract | null; - private readonly uiServer: AbstractUIServer | null; - private readonly storage!: Storage; + private workerConfiguration?: WorkerConfiguration; + private workerImplementation?: WorkerAbstract; + 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 readonly workerScript: string; private constructor() { super(); @@ -79,24 +79,16 @@ export class Bootstrap extends EventEmitter { this.stopping = false; this.initializedCounters = false; this.initializeCounters(); - this.workerImplementation = null; - this.workerScript = join( - dirname(fileURLToPath(import.meta.url)), - `ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`, - ); this.uiServer = UIServerFactory.getUIServerImplementation( Configuration.getConfigurationSection(ConfigurationSection.uiServer), ); - const performanceStorageConfiguration = - Configuration.getConfigurationSection( - ConfigurationSection.performanceStorage, - ); - performanceStorageConfiguration.enabled === true && - (this.storage = StorageFactory.getStorage( - performanceStorageConfiguration.type!, - performanceStorageConfiguration.uri!, - this.logPrefix(), - )); + this.on(ChargingStationWorkerMessageEvents.started, this.workerEventStarted); + this.on(ChargingStationWorkerMessageEvents.stopped, this.workerEventStopped); + this.on(ChargingStationWorkerMessageEvents.updated, this.workerEventUpdated); + this.on( + ChargingStationWorkerMessageEvents.performanceStatistics, + this.workerEventPerformanceStatistics, + ); Configuration.configurationChangeCallback = async () => Bootstrap.getInstance().restart(false); } @@ -112,12 +104,23 @@ export class Bootstrap extends EventEmitter { if (this.starting === false) { this.starting = true; this.initializeCounters(); - const workerConfiguration = Configuration.getConfigurationSection( + this.workerConfiguration = Configuration.getConfigurationSection( ConfigurationSection.worker, ); - this.initializeWorkerImplementation(workerConfiguration); + this.initializeWorkerImplementation(this.workerConfiguration); await this.workerImplementation?.start(); - await this.storage?.open(); + const performanceStorageConfiguration = + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ); + if (performanceStorageConfiguration.enabled === true) { + this.storage = StorageFactory.getStorage( + performanceStorageConfiguration.type!, + performanceStorageConfiguration.uri!, + this.logPrefix(), + ); + await this.storage?.open(); + } Configuration.getConfigurationSection(ConfigurationSection.uiServer) .enabled === true && this.uiServer?.start(); // Start ChargingStation object instance in worker thread @@ -142,13 +145,13 @@ export class Bootstrap extends EventEmitter { this.version } started with ${this.numberOfChargingStations.toString()} charging station(s) from ${this.numberOfChargingStationTemplates.toString()} configured charging station template(s) and ${ Configuration.workerDynamicPoolInUse() - ? `${workerConfiguration.poolMinSize?.toString()}/` + ? `${this.workerConfiguration.poolMinSize?.toString()}/` : '' }${this.workerImplementation?.size}${ Configuration.workerPoolInUse() - ? `/${workerConfiguration.poolMaxSize?.toString()}` + ? `/${this.workerConfiguration.poolMaxSize?.toString()}` : '' - } worker(s) concurrently running in '${workerConfiguration.processType}' mode${ + } worker(s) concurrently running in '${this.workerConfiguration.processType}' mode${ !isNullOrUndefined(this.workerImplementation?.maxElementsPerWorker) ? ` (${this.workerImplementation?.maxElementsPerWorker} charging station(s) per worker)` : '' @@ -191,9 +194,11 @@ export class Bootstrap extends EventEmitter { } } await this.workerImplementation?.stop(); - this.workerImplementation = null; + delete this.workerImplementation; + delete this.workerConfiguration; this.uiServer?.stop(); await this.storage?.close(); + delete this.storage; this.resetCounters(); this.initializedCounters = false; this.started = false; @@ -243,21 +248,23 @@ export class Bootstrap extends EventEmitter { ? Math.round(this.numberOfChargingStations / (availableParallelism() * 1.5)) : 1; } - this.workerImplementation === null && - (this.workerImplementation = WorkerFactory.getWorkerImplementation( - this.workerScript, - workerConfiguration.processType!, - { - workerStartDelay: workerConfiguration.startDelay, - elementStartDelay: workerConfiguration.elementStartDelay, - poolMaxSize: workerConfiguration.poolMaxSize!, - poolMinSize: workerConfiguration.poolMinSize!, - elementsPerWorker: elementsPerWorker ?? (workerConfiguration.elementsPerWorker as number), - poolOptions: { - messageHandler: this.messageHandler.bind(this) as (message: unknown) => void, - }, + this.workerImplementation = WorkerFactory.getWorkerImplementation( + join( + dirname(fileURLToPath(import.meta.url)), + `ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`, + ), + workerConfiguration.processType!, + { + workerStartDelay: workerConfiguration.startDelay, + elementStartDelay: workerConfiguration.elementStartDelay, + poolMaxSize: workerConfiguration.poolMaxSize!, + poolMinSize: workerConfiguration.poolMinSize!, + elementsPerWorker: elementsPerWorker ?? (workerConfiguration.elementsPerWorker as number), + poolOptions: { + messageHandler: this.messageHandler.bind(this) as (message: unknown) => void, }, - )); + }, + ); } private messageHandler( @@ -273,19 +280,15 @@ export class Bootstrap extends EventEmitter { try { switch (msg.event) { case ChargingStationWorkerMessageEvents.started: - this.workerEventStarted(msg.data as ChargingStationData); this.emit(ChargingStationWorkerMessageEvents.started, msg.data as ChargingStationData); break; case ChargingStationWorkerMessageEvents.stopped: - this.workerEventStopped(msg.data as ChargingStationData); this.emit(ChargingStationWorkerMessageEvents.stopped, msg.data as ChargingStationData); break; case ChargingStationWorkerMessageEvents.updated: - this.workerEventUpdated(msg.data as ChargingStationData); this.emit(ChargingStationWorkerMessageEvents.updated, msg.data as ChargingStationData); break; case ChargingStationWorkerMessageEvents.performanceStatistics: - this.workerEventPerformanceStatistics(msg.data as Statistics); this.emit( ChargingStationWorkerMessageEvents.performanceStatistics, msg.data as Statistics, @@ -346,7 +349,7 @@ export class Bootstrap extends EventEmitter { }; private workerEventPerformanceStatistics = (data: Statistics) => { - this.storage.storePerformanceStatistics(data) as void; + this.storage?.storePerformanceStatistics(data) as void; }; private initializeCounters() { diff --git a/src/charging-station/ui-server/UIServerFactory.ts b/src/charging-station/ui-server/UIServerFactory.ts index 0f75f60f..d3c34b58 100644 --- a/src/charging-station/ui-server/UIServerFactory.ts +++ b/src/charging-station/ui-server/UIServerFactory.ts @@ -17,7 +17,7 @@ export class UIServerFactory { public static getUIServerImplementation( uiServerConfiguration: UIServerConfiguration, - ): AbstractUIServer | null { + ): AbstractUIServer | undefined { if (UIServerUtils.isLoopback(uiServerConfiguration.options!.host!) === false) { console.warn( chalk.yellow( @@ -45,8 +45,6 @@ export class UIServerFactory { return new UIWebSocketServer(uiServerConfiguration); case ApplicationProtocol.HTTP: return new UIHttpServer(uiServerConfiguration); - default: - return null; } } } diff --git a/src/performance/storage/StorageFactory.ts b/src/performance/storage/StorageFactory.ts index cecaa489..31d0982e 100644 --- a/src/performance/storage/StorageFactory.ts +++ b/src/performance/storage/StorageFactory.ts @@ -13,8 +13,12 @@ export class StorageFactory { // This is intentional } - public static getStorage(type: StorageType, connectionUri: string, logPrefix: string): Storage { - let storageInstance: Storage | null = null; + public static getStorage( + type: StorageType, + connectionUri: string, + logPrefix: string, + ): Storage | undefined { + let storageInstance: Storage; switch (type) { case StorageType.JSON_FILE: storageInstance = new JsonFileStorage(connectionUri, logPrefix); diff --git a/src/worker/WorkerFactory.ts b/src/worker/WorkerFactory.ts index d248d3ba..608e8798 100644 --- a/src/worker/WorkerFactory.ts +++ b/src/worker/WorkerFactory.ts @@ -16,12 +16,12 @@ export class WorkerFactory { workerScript: string, workerProcessType: WorkerProcessType, workerOptions?: WorkerOptions, - ): WorkerAbstract | null { + ): WorkerAbstract | undefined { if (!isMainThread) { throw new Error('Cannot get a worker implementation outside the main thread'); } workerOptions = { ...DEFAULT_WORKER_OPTIONS, ...workerOptions }; - let workerImplementation: WorkerAbstract | null = null; + let workerImplementation: WorkerAbstract; switch (workerProcessType) { case WorkerProcessType.workerSet: workerImplementation = new WorkerSet(workerScript, workerOptions); -- 2.34.1