fix(scripted-alarms): resolve Medium code-review finding (Core.ScriptedAlarms-007)
Reorder persist/update in ApplyAsync, ReevaluateAsync, and ShelvingCheckAsync: SaveAsync is now called before the in-memory _alarms entry is advanced. A store failure therefore leaves both the persisted and in-memory views at the prior state rather than diverging, maintaining the invariant that startup recovery reflects actual persisted state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user