refactor: cleanup control flow in OCPP stack
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPRequestService.ts
index 880cf078df19b370457fe5c51c3204961bea61eb..0d59131fd157804c3de02cd4037fde289d82beed 100644 (file)
@@ -23,7 +23,13 @@ import {
   type ResponseCallback,
   type ResponseType,
 } from '../../types';
-import { Constants, cloneObject, handleSendMessageError, logger } from '../../utils';
+import {
+  Constants,
+  cloneObject,
+  handleSendMessageError,
+  isNullOrUndefined,
+  logger,
+} from '../../utils';
 
 const moduleName = 'OCPPRequestService';
 
@@ -349,10 +355,10 @@ export abstract class OCPPRequestService {
         /**
          * Function that will receive the request's error response
          *
-         * @param error -
+         * @param ocppError -
          * @param requestStatistic -
          */
-        const errorCallback = (error: OCPPError, requestStatistic = true): void => {
+        const errorCallback = (ocppError: OCPPError, requestStatistic = true): void => {
           if (requestStatistic === true && chargingStation.stationInfo?.enableStatistics === true) {
             chargingStation.performanceStatistics?.addRequestStatistic(
               commandName,
@@ -364,10 +370,36 @@ export abstract class OCPPRequestService {
               messageType,
             )} command ${commandName} with PDU %j:`,
             messagePayload,
-            error,
+            ocppError,
           );
           chargingStation.requests.delete(messageId);
-          reject(error);
+          reject(ocppError);
+        };
+
+        const rejectWithOcppError = (ocppError: OCPPError): void => {
+          // Reject response
+          if (messageType !== MessageType.CALL_MESSAGE) {
+            return reject(ocppError);
+          }
+          // Reject and remove request from the cache
+          return errorCallback(ocppError, false);
+        };
+
+        const bufferAndRejectWithOcppError = (ocppError: OCPPError): void => {
+          // Buffer
+          chargingStation.bufferMessage(messageToSend);
+          if (messageType === MessageType.CALL_MESSAGE) {
+            this.cacheRequestPromise(
+              chargingStation,
+              messageId,
+              messagePayload as JsonType,
+              commandName,
+              responseCallback,
+              errorCallback,
+            );
+          }
+          // Reject and keep request in the cache
+          return reject(ocppError);
         };
 
         if (chargingStation.stationInfo?.enableStatistics === true) {
@@ -384,19 +416,38 @@ export abstract class OCPPRequestService {
         if (chargingStation.isWebSocketConnectionOpened() === true) {
           const beginId = PerformanceStatistics.beginMeasure(commandName);
           const sendTimeout = setTimeout(() => {
-            return errorCallback(
+            return rejectWithOcppError(
               new OCPPError(
                 ErrorType.GENERIC_ERROR,
                 `Timeout for message id '${messageId}'`,
                 commandName,
                 (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FROZEN_OBJECT,
               ),
-              false,
             );
           }, OCPPConstants.OCPP_WEBSOCKET_TIMEOUT);
           chargingStation.wsConnection?.send(messageToSend, (error?: Error) => {
+            PerformanceStatistics.endMeasure(commandName, beginId);
             clearTimeout(sendTimeout);
-            if (error) {
+            if (isNullOrUndefined(error)) {
+              logger.debug(
+                `${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
+                  messageType,
+                )} payload: ${messageToSend}`,
+              );
+              if (messageType === MessageType.CALL_MESSAGE) {
+                this.cacheRequestPromise(
+                  chargingStation,
+                  messageId,
+                  messagePayload as JsonType,
+                  commandName,
+                  responseCallback,
+                  errorCallback,
+                );
+              } else {
+                // Resolve response
+                return resolve(messagePayload);
+              }
+            } else if (error) {
               const ocppError = new OCPPError(
                 ErrorType.GENERIC_ERROR,
                 `WebSocket errored for ${
@@ -406,65 +457,24 @@ export abstract class OCPPRequestService {
                 { name: error.name, message: error.message, stack: error.stack },
               );
               if (params?.skipBufferingOnError === false) {
-                // Buffer
-                chargingStation.bufferMessage(messageToSend);
-                // Reject and keep request in the cache
-                return reject(ocppError);
-              }
-              // Reject response
-              if (messageType !== MessageType.CALL_MESSAGE) {
-                return reject(ocppError);
+                return bufferAndRejectWithOcppError(ocppError);
               }
-              // Reject and remove request from the cache
-              return errorCallback(ocppError, false);
+              return rejectWithOcppError(ocppError);
             }
           });
-          if (messageType === MessageType.CALL_MESSAGE) {
-            this.cacheRequestPromise(
-              chargingStation,
-              messageId,
-              messagePayload as JsonType,
-              commandName,
-              responseCallback,
-              errorCallback,
-            );
-          }
-          logger.debug(
-            `${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
-              messageType,
-            )} payload: ${messageToSend}`,
-          );
-          PerformanceStatistics.endMeasure(commandName, beginId);
         } else {
+          const ocppError = new OCPPError(
+            ErrorType.GENERIC_ERROR,
+            `WebSocket closed for ${
+              params?.skipBufferingOnError === false ? '' : 'non '
+            }buffered message id '${messageId}' with content '${messageToSend}'`,
+            commandName,
+            (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FROZEN_OBJECT,
+          );
           if (params?.skipBufferingOnError === false) {
-            // Buffer
-            chargingStation.bufferMessage(messageToSend);
-            if (messageType === MessageType.CALL_MESSAGE) {
-              this.cacheRequestPromise(
-                chargingStation,
-                messageId,
-                messagePayload as JsonType,
-                commandName,
-                responseCallback,
-                errorCallback,
-              );
-            }
+            return bufferAndRejectWithOcppError(ocppError);
           }
-          // Reject and keep request in the cache
-          return reject(
-            new OCPPError(
-              ErrorType.GENERIC_ERROR,
-              `WebSocket closed for ${
-                params?.skipBufferingOnError === false ? '' : 'non '
-              }buffered message id '${messageId}' with content '${messageToSend}'`,
-              commandName,
-              (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FROZEN_OBJECT,
-            ),
-          );
-        }
-        // Resolve response
-        if (messageType !== MessageType.CALL_MESSAGE) {
-          return resolve(messagePayload);
+          return rejectWithOcppError(ocppError);
         }
       });
     }