From 8871e41d4c8bb685869b69a30d0c3f8066d9a741 Mon Sep 17 00:00:00 2001 From: andchiind Date: Tue, 11 Jun 2024 11:57:12 +0200 Subject: [PATCH] Add exception handling in event handlers --- backend/api/Database/Models/MissionRun.cs | 2 +- .../IsarConnectionEventHandler.cs | 15 +++++- .../api/EventHandlers/MissionEventHandler.cs | 46 +++++++++++++++++-- backend/api/EventHandlers/MqttEventHandler.cs | 38 ++++++++++++--- .../BatteryTimeseriesService.cs | 10 +++- .../ActionServices/PoseTimeseriesService.cs | 11 ++++- .../PressureTimeseriesService.cs | 10 +++- 7 files changed, 116 insertions(+), 16 deletions(-) diff --git a/backend/api/Database/Models/MissionRun.cs b/backend/api/Database/Models/MissionRun.cs index 1ba61015d..f957335be 100644 --- a/backend/api/Database/Models/MissionRun.cs +++ b/backend/api/Database/Models/MissionRun.cs @@ -114,7 +114,7 @@ public void UpdateWithIsarInfo(IsarMission isarMission) ); } - public static MissionStatus MissionStatusFromString(string status) + public static MissionStatus GetMissionStatusFromString(string status) { return status switch { diff --git a/backend/api/EventHandlers/IsarConnectionEventHandler.cs b/backend/api/EventHandlers/IsarConnectionEventHandler.cs index 179d4ef42..0d72cffc2 100644 --- a/backend/api/EventHandlers/IsarConnectionEventHandler.cs +++ b/backend/api/EventHandlers/IsarConnectionEventHandler.cs @@ -83,7 +83,20 @@ private async void OnIsarRobotHeartbeat(object? sender, MqttReceivedArgs mqttArg _isarConnectionTimers[robot.IsarId].Reset(); if (robot.IsarConnected) { return; } - await RobotService.UpdateRobotIsarConnected(robot.Id, true); + try + { + await RobotService.UpdateRobotIsarConnected(robot.Id, true); + } + catch (Exception e) + { + _logger.LogWarning( + "Failed to set robot to ISAR connected for ISAR ID '{IsarId}' ('{RobotName}')'. Exception: {Message} ", + isarRobotHeartbeat.IsarId, + isarRobotHeartbeat.RobotName, + e.Message + ); + return; + } } private void AddTimerForRobot(IsarRobotHeartbeatMessage isarRobotHeartbeat, Robot robot) diff --git a/backend/api/EventHandlers/MissionEventHandler.cs b/backend/api/EventHandlers/MissionEventHandler.cs index 41bbee6db..9dabc773f 100644 --- a/backend/api/EventHandlers/MissionEventHandler.cs +++ b/backend/api/EventHandlers/MissionEventHandler.cs @@ -119,7 +119,7 @@ or IsarCommunicationException } } - await CancellReturnToHomeOnNewMissionSchedule(missionRun); + await CancelReturnToHomeOnNewMissionSchedule(missionRun); _startMissionSemaphore.WaitOne(); try { await MissionScheduling.StartNextMissionRunIfSystemIsAvailable(missionRun.Robot.Id); } @@ -198,7 +198,21 @@ private async void OnEmergencyButtonPressedForRobot(object? sender, EmergencyBut try { await MissionScheduling.FreezeMissionRunQueueForRobot(e.RobotId); } catch (RobotNotFoundException) { return; } - var area = await FindRelevantRobotAreaForSafePositionMission(robot.Id); + + Area? area; + try + { + area = await FindRelevantRobotAreaForSafePositionMission(robot.Id); + } + catch (RobotNotFoundException) + { + _logger.LogWarning( + "Failed to see if robot was localised. Could not find robot with ID '{RobotId}'", + e.RobotId + ); + return; + } + if (area == null) { return; } try { await MissionScheduling.ScheduleMissionToDriveToSafePosition(e.RobotId, area.Id); } @@ -302,7 +316,7 @@ private async void OnEmergencyButtonDepressedForRobot(object? sender, EmergencyB return area; } - public async Task CancellReturnToHomeOnNewMissionSchedule(MissionRun missionRun) + public async Task CancelReturnToHomeOnNewMissionSchedule(MissionRun missionRun) { IList missionStatuses = [MissionStatus.Ongoing, MissionStatus.Pending, MissionStatus.Paused]; var existingReturnToHomeMissions = await MissionService.ReadMissionRuns(missionRun.Robot.Id, MissionRunType.ReturnHome, missionStatuses); @@ -311,11 +325,33 @@ public async Task CancellReturnToHomeOnNewMissionSchedule(MissionRun missionRun) { var returnToHomeMission = existingReturnToHomeMissions[0]; - if (!await LocalizationService.RobotIsOnSameDeckAsMission(missionRun.Robot.Id, missionRun.Area.Id)) + try { - _logger.LogWarning($"The robot {missionRun.Robot.Name} is localized on a different deck so the mission was not scheduled."); + if (!await LocalizationService.RobotIsOnSameDeckAsMission(missionRun.Robot.Id, missionRun.Area.Id)) + { + _logger.LogWarning($"The robot {missionRun.Robot.Name} is localized on a different deck so the mission was not scheduled."); + return; + } + } + catch (RobotNotFoundException) + { + string errorMessage = $"Could not cancel return to home mission on new mission schedule since {missionRun.Robot.Id} was not found"; + _logger.LogWarning("{Message}", errorMessage); + return; + } + catch (RobotCurrentAreaMissingException) + { + string errorMessage = $"Could not cancel return to home mission on new mission schedule since {missionRun.Robot.Id} did not have an Area associated with it"; + _logger.LogWarning("{Message}", errorMessage); return; } + catch (AreaNotFoundException) + { + string errorMessage = $"Could not cancel return to home mission on new mission schedule since {missionRun.Robot.Id} had Area with ID {missionRun.Area.Id} which could not be found"; + _logger.LogWarning("{Message}", errorMessage); + return; + } + if (returnToHomeMission.Status != MissionStatus.Pending) { diff --git a/backend/api/EventHandlers/MqttEventHandler.cs b/backend/api/EventHandlers/MqttEventHandler.cs index 4cadd8d84..30d21e055 100644 --- a/backend/api/EventHandlers/MqttEventHandler.cs +++ b/backend/api/EventHandlers/MqttEventHandler.cs @@ -131,8 +131,16 @@ private async void OnIsarRobotInfo(object? sender, MqttReceivedArgs mqttArgs) Status = RobotStatus.Available, }; - var newRobot = await robotService.CreateFromQuery(robotQuery); - _logger.LogInformation("Added robot '{RobotName}' with ISAR id '{IsarId}' to database", newRobot.Name, newRobot.IsarId); + try + { + var newRobot = await robotService.CreateFromQuery(robotQuery); + _logger.LogInformation("Added robot '{RobotName}' with ISAR id '{IsarId}' to database", newRobot.Name, newRobot.IsarId); + } + catch (DbUpdateException) + { + _logger.LogError($"Failed to add robot {robotQuery.Name} with to the database"); + return; + } return; } @@ -226,7 +234,7 @@ private async void OnIsarMissionUpdate(object? sender, MqttReceivedArgs mqttArgs var isarMission = (IsarMissionMessage)mqttArgs.Message; MissionStatus status; - try { status = MissionRun.MissionStatusFromString(isarMission.Status); } + try { status = MissionRun.GetMissionStatusFromString(isarMission.Status); } catch (ArgumentException e) { _logger.LogError(e, "Failed to parse mission status from MQTT message. Mission with ISARMissionId '{IsarMissionId}' was not updated", isarMission.MissionId); @@ -255,12 +263,31 @@ private async void OnIsarMissionUpdate(object? sender, MqttReceivedArgs mqttArgs { if (flotillaMissionRun.Status != MissionStatus.Successful) { - await robotService.UpdateCurrentArea(robot.Id, null); + try + { + await robotService.UpdateCurrentArea(robot.Id, null); + } + catch (RobotNotFoundException) + { + _logger.LogError("Could not find robot '{RobotName}' with ID '{Id}'", robot.Name, robot.Id); + return; + } signalRService.ReportGeneralFailToSignalR(robot, "Failed Localization Mission", $"Failed localization mission for robot {robot.Name}."); _logger.LogError("Localization mission for robot '{RobotName}' failed.", isarMission.RobotName); } - else { await robotService.UpdateCurrentArea(robot.Id, flotillaMissionRun.Area); } + else + { + try + { + await robotService.UpdateCurrentArea(robot.Id, flotillaMissionRun.Area); + } + catch (RobotNotFoundException) + { + _logger.LogError("Could not find robot '{RobotName}' with ID '{Id}'", robot.Name, robot.Id); + return; + } + } } try { await robotService.UpdateCurrentMissionId(robot.Id, null); } @@ -400,7 +427,6 @@ private async void OnIsarCloudHealthUpdate(object? sender, MqttReceivedArgs mqtt signalRService.ReportGeneralFailToSignalR(robot, messageTitle, message); teamsMessageService.TriggerTeamsMessageReceived(new TeamsMessageEventArgs(message)); - } } } diff --git a/backend/api/Services/ActionServices/BatteryTimeseriesService.cs b/backend/api/Services/ActionServices/BatteryTimeseriesService.cs index 7285179df..4bc7600e3 100644 --- a/backend/api/Services/ActionServices/BatteryTimeseriesService.cs +++ b/backend/api/Services/ActionServices/BatteryTimeseriesService.cs @@ -18,7 +18,15 @@ public async Task AddBatteryEntry(float batteryLevel, string isarId) return; } - if (Math.Abs(batteryLevel - robot.BatteryLevel) > Tolerance) await robotService.UpdateRobotBatteryLevel(robot.Id, batteryLevel); + try + { + if (Math.Abs(batteryLevel - robot.BatteryLevel) > Tolerance) await robotService.UpdateRobotBatteryLevel(robot.Id, batteryLevel); + } + catch (Exception e) + { + logger.LogWarning("Failed to update robot battery value for robot with ID '{isarId}'. Exception: {message}", isarId, e.Message); + return; + } logger.LogDebug("Updated battery on robot '{RobotName}' with ISAR id '{IsarId}'", robot.Name, robot.IsarId); } diff --git a/backend/api/Services/ActionServices/PoseTimeseriesService.cs b/backend/api/Services/ActionServices/PoseTimeseriesService.cs index 84c18690e..2458d5ee0 100644 --- a/backend/api/Services/ActionServices/PoseTimeseriesService.cs +++ b/backend/api/Services/ActionServices/PoseTimeseriesService.cs @@ -17,7 +17,16 @@ public async Task AddPoseEntry(Pose pose, string isarId) return; } - await robotService.UpdateRobotPose(robot.Id, pose); + try + { + await robotService.UpdateRobotPose(robot.Id, pose); + } + catch (Exception e) + { + logger.LogWarning("Failed to update robot pose value for robot with ID '{isarId}'. Exception: {message}", isarId, e.Message); + return; + } + logger.LogDebug("Updated pose on robot '{RobotName}' with ISAR id '{IsarId}'", robot.Name, robot.IsarId); } } diff --git a/backend/api/Services/ActionServices/PressureTimeseriesService.cs b/backend/api/Services/ActionServices/PressureTimeseriesService.cs index c77420531..ef5b79db9 100644 --- a/backend/api/Services/ActionServices/PressureTimeseriesService.cs +++ b/backend/api/Services/ActionServices/PressureTimeseriesService.cs @@ -18,7 +18,15 @@ public async Task AddPressureEntry(float pressureLevel, string isarId) return; } - if (robot.PressureLevel is null || Math.Abs(pressureLevel - (float)robot.PressureLevel) > Tolerance) await robotService.UpdateRobotPressureLevel(robot.Id, pressureLevel); + try + { + if (robot.PressureLevel is null || Math.Abs(pressureLevel - (float)robot.PressureLevel) > Tolerance) await robotService.UpdateRobotPressureLevel(robot.Id, pressureLevel); + } + catch (Exception e) + { + logger.LogWarning("Failed to update robot pressure value for robot with ID '{isarId}'. Exception: {message}", isarId, e.Message); + return; + } logger.LogDebug("Updated pressure on robot '{RobotName}' with ISAR id '{IsarId}'", robot.Name, robot.IsarId); }