]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
perf: emit events only if needed
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 21 Oct 2025 20:47:09 +0000 (22:47 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 21 Oct 2025 20:47:09 +0000 (22:47 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/Bootstrap.ts
src/charging-station/ChargingStation.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts
src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts
src/charging-station/ocpp/2.0/OCPP20ResponseService.ts
src/charging-station/ocpp/OCPPRequestService.ts
src/charging-station/ocpp/OCPPServiceUtils.ts

index e9d9eba66f2d5b4b17d6fc6bde15c6baf3f59764..8106d29a3c6e33dd951632e0c69940ee54861cfe 100644 (file)
@@ -367,7 +367,7 @@ export class AutomaticTransactionGenerator {
       `${this.logPrefix(connectorId)} stopped with connector status: %j`,
       this.connectorsStatus.get(connectorId)
     )
-    this.chargingStation.emit(ChargingStationEvents.updated)
+    this.chargingStation.emitChargingStationEvent(ChargingStationEvents.updated)
   }
 
   private readonly logPrefix = (connectorId?: number): string => {
@@ -406,7 +406,7 @@ export class AutomaticTransactionGenerator {
     this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     this.connectorsStatus.get(connectorId)!.start = true
-    this.chargingStation.emit(ChargingStationEvents.updated)
+    this.chargingStation.emitChargingStationEvent(ChargingStationEvents.updated)
   }
 
   private startConnectors (stopAbsoluteDuration?: boolean): void {
index d249efb5d482cf4d9c13d34dd10c9987587044ab..0629ad852606a3fe5c66b3337dad7d80ec017bcb 100644 (file)
@@ -468,27 +468,69 @@ export class Bootstrap extends EventEmitter {
     const { data, event } = msg
     try {
       switch (event) {
+        case ChargingStationWorkerMessageEvents.accepted:
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.accepted) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.accepted, data)
+          }
+          break
         case ChargingStationWorkerMessageEvents.added:
-          this.emit(ChargingStationWorkerMessageEvents.added, data)
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.added) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.added, data)
+          }
+          break
+        case ChargingStationWorkerMessageEvents.connected:
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.connected) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.connected, data)
+          }
+          break
+        case ChargingStationWorkerMessageEvents.connectorStatusChanged:
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.connectorStatusChanged) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.connectorStatusChanged, data)
+          }
           break
         case ChargingStationWorkerMessageEvents.deleted:
-          this.emit(ChargingStationWorkerMessageEvents.deleted, data)
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.deleted) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.deleted, data)
+          }
+          break
+        case ChargingStationWorkerMessageEvents.disconnected:
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.disconnected) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.disconnected, data)
+          }
+          break
+        case ChargingStationWorkerMessageEvents.pending:
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.pending) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.pending, data)
+          }
           break
         case ChargingStationWorkerMessageEvents.performanceStatistics:
-          this.emit(ChargingStationWorkerMessageEvents.performanceStatistics, data)
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.performanceStatistics) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.performanceStatistics, data)
+          }
+          break
+        case ChargingStationWorkerMessageEvents.rejected:
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.rejected) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.rejected, data)
+          }
           break
         case ChargingStationWorkerMessageEvents.started:
-          this.emit(ChargingStationWorkerMessageEvents.started, data)
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.started) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.started, data)
+          }
           break
         case ChargingStationWorkerMessageEvents.stopped:
-          this.emit(ChargingStationWorkerMessageEvents.stopped, data)
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.stopped) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.stopped, data)
+          }
           break
         case ChargingStationWorkerMessageEvents.updated:
-          this.emit(ChargingStationWorkerMessageEvents.updated, data)
+          if (this.listenerCount(ChargingStationWorkerMessageEvents.updated) > 0) {
+            this.emit(ChargingStationWorkerMessageEvents.updated, data)
+          }
           break
         default:
           throw new BaseError(
-            `Unknown charging station worker message event: '${event}' received with data: ${JSON.stringify(
+            `Unknown charging station worker message event: '${event as string}' received with data: ${JSON.stringify(
               data,
               undefined,
               2
index 4c55961195f493c79de79a66c2a6bae664d2bc9d..721d8625ec7f04c29ccd0aa295f7bec5c44b27c4 100644 (file)
@@ -329,10 +329,22 @@ export class ChargingStation extends EventEmitter {
     this.templateFileWatcher?.unref()
     deleteConfiguration && rmSync(this.configurationFile, { force: true })
     this.chargingStationWorkerBroadcastChannel.unref()
-    this.emit(ChargingStationEvents.deleted)
+    this.emitChargingStationEvent(ChargingStationEvents.deleted)
     this.removeAllListeners()
   }
 
+  /**
+   * Emit a ChargingStation event only if there are listeners registered for it.
+   * This optimizes performance by avoiding unnecessary event emission.
+   * @param event - The ChargingStation event to emit
+   * @param args - Arguments to pass to the event listeners
+   */
+  public emitChargingStationEvent (event: ChargingStationEvents, ...args: unknown[]): void {
+    if (this.listenerCount(event) > 0) {
+      this.emit(event, ...args)
+    }
+  }
+
   public getAuthorizeRemoteTxRequests (): boolean {
     const authorizeRemoteTxRequests = getConfigurationKey(
       this,
@@ -863,7 +875,7 @@ export class ChargingStation extends EventEmitter {
           }
         )
         this.started = true
-        this.emit(ChargingStationEvents.started)
+        this.emitChargingStationEvent(ChargingStationEvents.started)
         this.starting = false
       } else {
         logger.warn(`${this.logPrefix()} Charging station is already starting...`)
@@ -886,7 +898,7 @@ export class ChargingStation extends EventEmitter {
       this.automaticTransactionGenerator?.start(stopAbsoluteDuration)
     }
     this.saveAutomaticTransactionGeneratorConfiguration()
-    this.emit(ChargingStationEvents.updated)
+    this.emitChargingStationEvent(ChargingStationEvents.updated)
   }
 
   public startHeartbeat (): void {
@@ -1001,7 +1013,7 @@ export class ChargingStation extends EventEmitter {
         this.started = false
         this.saveConfiguration()
         this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
-        this.emit(ChargingStationEvents.stopped)
+        this.emitChargingStationEvent(ChargingStationEvents.stopped)
         this.stopping = false
       } else {
         logger.warn(`${this.logPrefix()} Charging station is already stopping...`)
@@ -1020,7 +1032,7 @@ export class ChargingStation extends EventEmitter {
       this.automaticTransactionGenerator?.stop()
     }
     this.saveAutomaticTransactionGeneratorConfiguration()
-    this.emit(ChargingStationEvents.updated)
+    this.emitChargingStationEvent(ChargingStationEvents.updated)
   }
 
   public stopMeterValues (connectorId: number): void {
@@ -1066,7 +1078,7 @@ export class ChargingStation extends EventEmitter {
   }
 
   private add (): void {
-    this.emit(ChargingStationEvents.added)
+    this.emitChargingStationEvent(ChargingStationEvents.added)
   }
 
   private clearIntervalFlushMessageBuffer (): void {
@@ -1481,7 +1493,7 @@ export class ChargingStation extends EventEmitter {
       commandName,
       commandPayload
     )
-    this.emit(ChargingStationEvents.updated)
+    this.emitChargingStationEvent(ChargingStationEvents.updated)
   }
 
   private handleResponseMessage (response: Response): void {
@@ -1918,8 +1930,8 @@ export class ChargingStation extends EventEmitter {
   }
 
   private onClose (code: WebSocketCloseEventStatusCode, reason: Buffer): void {
-    this.emit(ChargingStationEvents.disconnected)
-    this.emit(ChargingStationEvents.updated)
+    this.emitChargingStationEvent(ChargingStationEvents.disconnected)
+    this.emitChargingStationEvent(ChargingStationEvents.updated)
     switch (code) {
       // Normal close
       case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS:
@@ -1941,7 +1953,7 @@ export class ChargingStation extends EventEmitter {
         this.started &&
           this.reconnect()
             .then(() => {
-              this.emit(ChargingStationEvents.updated)
+              this.emitChargingStationEvent(ChargingStationEvents.updated)
               return undefined
             })
             .catch((error: unknown) =>
@@ -2052,8 +2064,8 @@ export class ChargingStation extends EventEmitter {
 
   private async onOpen (): Promise<void> {
     if (this.isWebSocketConnectionOpened()) {
-      this.emit(ChargingStationEvents.connected)
-      this.emit(ChargingStationEvents.updated)
+      this.emitChargingStationEvent(ChargingStationEvents.connected)
+      this.emitChargingStationEvent(ChargingStationEvents.updated)
       logger.info(
         `${this.logPrefix()} Connection to OCPP server through ${
           this.wsConnectionUrl.href
@@ -2097,7 +2109,7 @@ export class ChargingStation extends EventEmitter {
           `${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount.toString()}) or retry disabled (${this.stationInfo?.registrationMaxRetries?.toString()})`
         )
       }
-      this.emit(ChargingStationEvents.updated)
+      this.emitChargingStationEvent(ChargingStationEvents.updated)
     } else {
       logger.warn(
         `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.href} failed`
index 8b530e2a972137fa99a84f50371965aee90e9519..5e7a4a6b01805b3968bbbd8f02d0e43d8a8ce8e9 100644 (file)
@@ -655,8 +655,10 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       response,
       commandName
     )
-    // Emit command name event to allow delayed handling
-    this.emit(commandName, chargingStation, commandPayload, response)
+    // Emit command name event to allow delayed handling only if there are listeners
+    if (this.listenerCount(commandName) > 0) {
+      this.emit(commandName, chargingStation, commandPayload, response)
+    }
   }
 
   private async handleRequestCancelReservation (
index 871249c5309e01aad6683a5aaab2736de3e1af77..0921078b3ba144a5c0a2bcc567a79740e6071b54 100644 (file)
@@ -526,11 +526,11 @@ export class OCPP16ResponseService extends OCPPResponseService {
         )
       }
       if (chargingStation.inAcceptedState()) {
-        chargingStation.emit(ChargingStationEvents.accepted)
+        chargingStation.emitChargingStationEvent(ChargingStationEvents.accepted)
       } else if (chargingStation.inPendingState()) {
-        chargingStation.emit(ChargingStationEvents.pending)
+        chargingStation.emitChargingStationEvent(ChargingStationEvents.pending)
       } else if (chargingStation.inRejectedState()) {
-        chargingStation.emit(ChargingStationEvents.rejected)
+        chargingStation.emitChargingStationEvent(ChargingStationEvents.rejected)
       }
       const logMsg = `${chargingStation.logPrefix()} Charging station in '${
         payload.status
index c77014e08b127960b6fc1a06588d89933a2e065c..572fc211651db890decf906cc44a021c8a821d8a 100644 (file)
@@ -180,8 +180,10 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
       response,
       commandName
     )
-    // Emit command name event to allow delayed handling
-    this.emit(commandName, chargingStation, commandPayload, response)
+    // Emit command name event to allow delayed handling only if there are listeners
+    if (this.listenerCount(commandName) > 0) {
+      this.emit(commandName, chargingStation, commandPayload, response)
+    }
   }
 
   private buildReportData (
index c092059f2383d243a3606ad305a73b906f63f0dd..ec76b2f8c77ac96d5a0b4c605c25a656a109502e 100644 (file)
@@ -204,11 +204,11 @@ export class OCPP20ResponseService extends OCPPResponseService {
         )
       }
       if (chargingStation.inAcceptedState()) {
-        chargingStation.emit(ChargingStationEvents.accepted)
+        chargingStation.emitChargingStationEvent(ChargingStationEvents.accepted)
       } else if (chargingStation.inPendingState()) {
-        chargingStation.emit(ChargingStationEvents.pending)
+        chargingStation.emitChargingStationEvent(ChargingStationEvents.pending)
       } else if (chargingStation.inRejectedState()) {
-        chargingStation.emit(ChargingStationEvents.rejected)
+        chargingStation.emitChargingStationEvent(ChargingStationEvents.rejected)
       }
       const logMsg = `${chargingStation.logPrefix()} Charging station in '${
         payload.status
index 439d656fbd1da7480a0998905c8f1b181592795c..d5b944f127fc49a0af6ff3f5f1a83e7abd0a39c6 100644 (file)
@@ -282,7 +282,7 @@ export abstract class OCPPRequestService {
             })
             .finally(() => {
               chargingStation.requests.delete(messageId)
-              chargingStation.emit(ChargingStationEvents.updated)
+              chargingStation.emitChargingStationEvent(ChargingStationEvents.updated)
             })
             .catch(reject)
         }
@@ -307,7 +307,7 @@ export abstract class OCPPRequestService {
             ocppError
           )
           chargingStation.requests.delete(messageId)
-          chargingStation.emit(ChargingStationEvents.updated)
+          chargingStation.emitChargingStationEvent(ChargingStationEvents.updated)
           reject(ocppError)
         }
 
index c7ccb90522765733044afb5ce28317c4827ae40a..36d66fcb4e3adee5653b2b368c254071915dac62 100644 (file)
@@ -192,7 +192,7 @@ export const sendAndSetConnectorStatus = async (
     )
   }
   connectorStatus.status = status
-  chargingStation.emit(ChargingStationEvents.connectorStatusChanged, {
+  chargingStation.emitChargingStationEvent(ChargingStationEvents.connectorStatusChanged, {
     connectorId,
     ...connectorStatus,
   })