fix(siteruntime): faulted expression-eval task clears _evalInFlight instead of killing the AlarmActor trigger (plan R2-03 T3)

This commit is contained in:
Joseph Doherty
2026-07-13 09:50:40 -04:00
parent f149626a76
commit 15018e4158
2 changed files with 58 additions and 1 deletions
@@ -1054,4 +1054,31 @@ public class AlarmActorTests : TestKit, IDisposable
var change = instanceProbe.ExpectMsg<AlarmStateChanged>(TimeSpan.FromSeconds(10));
Assert.Equal(AlarmState.Active, change.State);
}
[Fact]
public void ExpressionEvalTaskFault_DoesNotKillTheAlarmTrigger()
{
var expr = CompileRawTriggerExpression("true");
var alarmConfig = new ResolvedAlarm
{
CanonicalName = "ExprFaultAlarm",
TriggerType = "Expression",
TriggerConfiguration = "{\"expression\":\"true\"}",
PriorityLevel = 1
};
var instanceProbe = CreateTestProbe();
var alarm = ActorOf(Props.Create(() => new AlarmActor(
"ExprFaultAlarm", "Pump1", instanceProbe.Ref, alarmConfig,
null, _sharedLibrary, _options,
NullLogger<AlarmActor>.Instance, expr)));
// Simulate the faulted scheduler task: must be handled (logged, in-flight
// cleared, false applied) — NOT an unhandled Status.Failure.
alarm.Tell(new AlarmActor.ExpressionEvalFailed(new ObjectDisposedException("scheduler")));
// The trigger must still be alive: the next change evaluates and activates.
alarm.Tell(new AttributeValueChanged("Pump1", "A", "A", 1, "Good", DateTimeOffset.UtcNow));
var change = instanceProbe.ExpectMsg<AlarmStateChanged>(TimeSpan.FromSeconds(10));
Assert.Equal(AlarmState.Active, change.State);
}
}