feat(runtime): ScriptedAlarmActor state machine (engine wiring tracked as F9)

This commit is contained in:
Joseph Doherty
2026-05-26 05:09:03 -04:00
parent 39729bfe21
commit 95ef533822
2 changed files with 104 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
using Akka.Actor;
using Akka.Event;
namespace ZB.MOM.WW.OtOpcUa.Runtime.ScriptedAlarms;
public enum ScriptedAlarmActorState { Inactive, Active, Acknowledged }
/// <summary>
/// State machine wrapping a single scripted alarm. Transitions:
/// <c>Inactive → Active → Acknowledged → Inactive</c>.
///
/// Engine wiring (compile alarm expression via <c>AlarmConditionService</c>, persist state to
/// <c>ScriptedAlarmState</c> ConfigDb table on <c>PreRestart</c>, emit history rows to
/// <c>HistorianAdapter</c>) is staged for follow-up F9. This skeleton owns the state machine
/// so DriverHostActor can spawn it as a child.
/// </summary>
public sealed class ScriptedAlarmActor : ReceiveActor
{
public sealed record ConditionMet(string Reason);
public sealed record AcknowledgeAlarm(string Actor);
public sealed record ConditionCleared;
public sealed record StateChanged(string AlarmId, ScriptedAlarmActorState State, DateTime AtUtc);
private readonly string _alarmId;
private readonly ILoggingAdapter _log = Context.GetLogger();
private ScriptedAlarmActorState _state = ScriptedAlarmActorState.Inactive;
public static Props Props(string alarmId) =>
Akka.Actor.Props.Create(() => new ScriptedAlarmActor(alarmId));
public ScriptedAlarmActor(string alarmId)
{
_alarmId = alarmId;
Receive<ConditionMet>(msg =>
{
if (_state != ScriptedAlarmActorState.Inactive) return;
Transition(ScriptedAlarmActorState.Active);
});
Receive<AcknowledgeAlarm>(msg =>
{
if (_state != ScriptedAlarmActorState.Active) return;
Transition(ScriptedAlarmActorState.Acknowledged);
});
Receive<ConditionCleared>(_ =>
{
if (_state == ScriptedAlarmActorState.Inactive) return;
Transition(ScriptedAlarmActorState.Inactive);
});
}
private void Transition(ScriptedAlarmActorState next)
{
var prev = _state;
_state = next;
_log.Info("ScriptedAlarm {Id}: {From} → {To}", _alarmId, prev, next);
Context.Parent.Tell(new StateChanged(_alarmId, next, DateTime.UtcNow));
// F9: emit history row via HistorianAdapter; persist state to ScriptedAlarmState DB.
}
}