From a1cfaa16c9e91765bee3c54cd0208ad01c154aa4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 21 Feb 2024 21:57:14 +0100 Subject: [PATCH] fix(ui): ensure UI server can only be started once MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/charging-station/Bootstrap.ts | 46 +++++++++++++------ .../ui-server/AbstractUIServer.ts | 2 +- .../ui-server/UIServerFactory.ts | 7 +-- ui/web/.vscode/extensions.json | 2 +- .../components/actions/SetSupervisionUrl.vue | 2 +- .../components/actions/StartTransaction.vue | 2 +- .../src/components/buttons/ReloadButton.vue | 1 - .../charging-stations/CSConnector.vue | 2 +- .../components/charging-stations/CSData.vue | 2 +- .../components/charging-stations/CSTable.vue | 3 +- 10 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/charging-station/Bootstrap.ts b/src/charging-station/Bootstrap.ts index 433b04cd..047b321b 100644 --- a/src/charging-station/Bootstrap.ts +++ b/src/charging-station/Bootstrap.ts @@ -65,7 +65,7 @@ interface TemplateChargingStations { export class Bootstrap extends EventEmitter { private static instance: Bootstrap | null = null private workerImplementation?: WorkerAbstract - private readonly uiServer?: AbstractUIServer + private readonly uiServer: AbstractUIServer private storage?: Storage private readonly templatesChargingStations: Map private readonly version: string = version @@ -73,6 +73,7 @@ export class Bootstrap extends EventEmitter { private started: boolean private starting: boolean private stopping: boolean + private uiServerStarted: boolean private constructor () { super() @@ -85,10 +86,11 @@ export class Bootstrap extends EventEmitter { this.started = false this.starting = false this.stopping = false - this.templatesChargingStations = new Map() + this.uiServerStarted = false this.uiServer = UIServerFactory.getUIServerImplementation( Configuration.getConfigurationSection(ConfigurationSection.uiServer) ) + this.templatesChargingStations = new Map() this.initializedCounters = false this.initializeCounters() Configuration.configurationChangeCallback = async () => { @@ -189,8 +191,15 @@ export class Bootstrap extends EventEmitter { ) await this.storage?.open() } - Configuration.getConfigurationSection(ConfigurationSection.uiServer) - .enabled === true && this.uiServer?.start() + if ( + !this.uiServerStarted && + Configuration.getConfigurationSection( + ConfigurationSection.uiServer + ).enabled === true + ) { + this.uiServer.start() + this.uiServerStarted = true + } // Start ChargingStation object instance in worker thread // eslint-disable-next-line @typescript-eslint/no-non-null-assertion for (const stationTemplateUrl of Configuration.getStationTemplateUrls()!) { @@ -246,7 +255,7 @@ export class Bootstrap extends EventEmitter { if (this.started) { if (!this.stopping) { this.stopping = true - await this.uiServer?.sendInternalRequest( + await this.uiServer.sendInternalRequest( this.uiServer.buildProtocolRequest( generateUUID(), ProcedureName.STOP_CHARGING_STATION, @@ -261,7 +270,7 @@ export class Bootstrap extends EventEmitter { await this.workerImplementation?.stop() delete this.workerImplementation this.removeAllListeners() - this.uiServer?.chargingStations.clear() + this.uiServer.clearCaches() this.initializedCounters = false await this.storage?.close() delete this.storage @@ -277,8 +286,14 @@ export class Bootstrap extends EventEmitter { private async restart (): Promise { await this.stop() - Configuration.getConfigurationSection(ConfigurationSection.uiServer) - .enabled !== true && this.uiServer?.stop() + if ( + this.uiServerStarted && + Configuration.getConfigurationSection(ConfigurationSection.uiServer) + .enabled !== true + ) { + this.uiServer.stop() + this.uiServerStarted = false + } await this.start() } @@ -400,7 +415,7 @@ export class Bootstrap extends EventEmitter { } private readonly workerEventAdded = (data: ChargingStationData): void => { - this.uiServer?.chargingStations.set(data.stationInfo.hashId, data) + this.uiServer.chargingStations.set(data.stationInfo.hashId, data) logger.info( `${this.logPrefix()} ${moduleName}.workerEventAdded: Charging station ${ data.stationInfo.chargingStationId @@ -411,7 +426,7 @@ export class Bootstrap extends EventEmitter { } private readonly workerEventDeleted = (data: ChargingStationData): void => { - this.uiServer?.chargingStations.delete(data.stationInfo.hashId) + this.uiServer.chargingStations.delete(data.stationInfo.hashId) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const templateChargingStations = this.templatesChargingStations.get( data.stationInfo.templateName @@ -428,7 +443,7 @@ export class Bootstrap extends EventEmitter { } private readonly workerEventStarted = (data: ChargingStationData): void => { - this.uiServer?.chargingStations.set(data.stationInfo.hashId, data) + this.uiServer.chargingStations.set(data.stationInfo.hashId, data) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ++this.templatesChargingStations.get(data.stationInfo.templateName)!.started logger.info( @@ -441,7 +456,7 @@ export class Bootstrap extends EventEmitter { } private readonly workerEventStopped = (data: ChargingStationData): void => { - this.uiServer?.chargingStations.set(data.stationInfo.hashId, data) + this.uiServer.chargingStations.set(data.stationInfo.hashId, data) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --this.templatesChargingStations.get(data.stationInfo.templateName)!.started logger.info( @@ -454,7 +469,7 @@ export class Bootstrap extends EventEmitter { } private readonly workerEventUpdated = (data: ChargingStationData): void => { - this.uiServer?.chargingStations.set(data.stationInfo.hashId, data) + this.uiServer.chargingStations.set(data.stationInfo.hashId, data) } private readonly workerEventPerformanceStatistics = (data: Statistics): void => { @@ -485,7 +500,7 @@ export class Bootstrap extends EventEmitter { started: 0, indexes: new Set() }) - this.uiServer?.chargingStationTemplates.add(templateName) + this.uiServer.chargingStationTemplates.add(templateName) } if (this.templatesChargingStations.size !== stationTemplateUrls.length) { console.error( @@ -544,7 +559,8 @@ export class Bootstrap extends EventEmitter { this.stop() .then(() => { console.info(chalk.green('Graceful shutdown')) - this.uiServer?.stop() + this.uiServer.stop() + this.uiServerStarted = false this.waitChargingStationsStopped() .then(() => { exit(exitCodes.succeeded) diff --git a/src/charging-station/ui-server/AbstractUIServer.ts b/src/charging-station/ui-server/AbstractUIServer.ts index e24a5769..61593db5 100644 --- a/src/charging-station/ui-server/AbstractUIServer.ts +++ b/src/charging-station/ui-server/AbstractUIServer.ts @@ -66,7 +66,7 @@ export abstract class AbstractUIServer { this.clearCaches() } - private clearCaches (): void { + public clearCaches (): void { this.chargingStations.clear() this.chargingStationTemplates.clear() } diff --git a/src/charging-station/ui-server/UIServerFactory.ts b/src/charging-station/ui-server/UIServerFactory.ts index d6dea71b..d7de7ddd 100644 --- a/src/charging-station/ui-server/UIServerFactory.ts +++ b/src/charging-station/ui-server/UIServerFactory.ts @@ -20,7 +20,7 @@ export class UIServerFactory { public static getUIServerImplementation ( uiServerConfiguration: UIServerConfiguration - ): AbstractUIServer | undefined { + ): AbstractUIServer { if ( uiServerConfiguration.authentication?.enabled === true && !Object.values(AuthenticationType).includes(uiServerConfiguration.authentication.type) @@ -59,10 +59,11 @@ export class UIServerFactory { uiServerConfiguration.version = ApplicationProtocolVersion.VERSION_11 } switch (uiServerConfiguration.type) { - case ApplicationProtocol.WS: - return new UIWebSocketServer(uiServerConfiguration) case ApplicationProtocol.HTTP: return new UIHttpServer(uiServerConfiguration) + case ApplicationProtocol.WS: + default: + return new UIWebSocketServer(uiServerConfiguration) } } } diff --git a/ui/web/.vscode/extensions.json b/ui/web/.vscode/extensions.json index fc76e3d0..1d8c5898 100644 --- a/ui/web/.vscode/extensions.json +++ b/ui/web/.vscode/extensions.json @@ -7,6 +7,6 @@ "sonarsource.sonarlint-vscode", "streetsidesoftware.code-spell-checker", "Vue.volar", - "zixuanchen.vitest-explorer" + "vitest.explorer" ] } diff --git a/ui/web/src/components/actions/SetSupervisionUrl.vue b/ui/web/src/components/actions/SetSupervisionUrl.vue index 33b6767b..e50316bf 100644 --- a/ui/web/src/components/actions/SetSupervisionUrl.vue +++ b/ui/web/src/components/actions/SetSupervisionUrl.vue @@ -36,7 +36,7 @@