diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs index e23d80a..cc3f4e9 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs @@ -238,8 +238,12 @@ public sealed class ScriptedAlarmEngine : IDisposable try { var result = op(state.Condition); - _alarms[alarmId] = state with { Condition = result.State }; + // Persist BEFORE updating in-memory so a store failure leaves both + // in-memory and persisted at the prior state rather than diverging. + // If SaveAsync throws the in-memory _alarms entry stays unchanged and + // the exception propagates to the caller. (Core.ScriptedAlarms-007) await _store.SaveAsync(result.State, ct).ConfigureAwait(false); + _alarms[alarmId] = state with { Condition = result.State }; if (result.Emission != EmissionKind.None) EmitEvent(state, result.State, result.Emission); } finally { _evalGate.Release(); } @@ -279,8 +283,10 @@ public sealed class ScriptedAlarmEngine : IDisposable state, state.Condition, _clock(), ct).ConfigureAwait(false); if (!ReferenceEquals(newState, state.Condition)) { - _alarms[id] = state with { Condition = newState }; + // Persist before updating in-memory so a store failure leaves + // both sides at the prior state. (Core.ScriptedAlarms-007) await _store.SaveAsync(newState, ct).ConfigureAwait(false); + _alarms[id] = state with { Condition = newState }; } } } @@ -422,8 +428,10 @@ public sealed class ScriptedAlarmEngine : IDisposable var result = Part9StateMachine.ApplyShelvingCheck(state.Condition, now); if (!ReferenceEquals(result.State, state.Condition)) { - _alarms[id] = state with { Condition = result.State }; + // Persist before updating in-memory so a store failure leaves + // both sides at the prior state. (Core.ScriptedAlarms-007) await _store.SaveAsync(result.State, ct).ConfigureAwait(false); + _alarms[id] = state with { Condition = result.State }; if (result.Emission != EmissionKind.None) EmitEvent(state, result.State, result.Emission); }