feat(historian): honor per-alarm HistorizeToAveva opt-out at the durable write

This commit is contained in:
Joseph Doherty
2026-06-11 12:48:13 -04:00
parent fa839d1dbf
commit 8012509584
6 changed files with 78 additions and 9 deletions
@@ -183,7 +183,8 @@ public sealed class HistorianAdapterActorTests : RuntimeActorTestBase
int severity = 750,
string alarmTypeName = "LimitAlarm",
string? comment = "note",
string transitionKind = "Activated") => new(
string transitionKind = "Activated",
bool historizeToAveva = true) => new(
AlarmId: "alm-9",
EquipmentPath: "Area/Line/Equip",
AlarmName: "HiHi",
@@ -193,7 +194,8 @@ public sealed class HistorianAdapterActorTests : RuntimeActorTestBase
User: "operator1",
TimestampUtc: DateTime.UtcNow,
AlarmTypeName: alarmTypeName,
Comment: comment);
Comment: comment,
HistorizeToAveva: historizeToAveva);
/// <summary>Alerts translate (T6): an <see cref="AlarmTransitionEvent"/> off the <c>alerts</c> topic
/// is translated to an <see cref="AlarmHistorianEvent"/> and historized by default (unknown role).
@@ -251,6 +253,23 @@ public sealed class HistorianAdapterActorTests : RuntimeActorTestBase
AwaitAssert(() => sink.EnqueueCount.ShouldBe(1), Settle);
}
/// <summary>Per-alarm opt-out (T8b): a Primary node must NOT historize a transition whose
/// <c>HistorizeToAveva</c> is <c>false</c> — that flag is a per-alarm opt-out of DURABLE
/// historization only. The live <c>alerts</c> fan-out already happened upstream (the publish is NOT
/// gated on this flag), so only the durable sink write is suppressed.</summary>
[Fact]
public void Primary_node_does_not_historize_when_opted_out()
{
var sink = new RecordingSink();
var actor = Sys.ActorOf(HistorianAdapterActor.Props(sink, LocalNode));
TellRedundancyRole(actor, RedundancyRole.Primary);
actor.Tell(SampleTransition(historizeToAveva: false));
ExpectNoMsg(Settle);
sink.EnqueueCount.ShouldBe(0);
}
/// <summary>Severity buckets (T9): the OPC UA 11000 numeric severity on the transition maps onto
/// the coarse <see cref="AlarmSeverity"/> at the same ceilings <c>ScriptedAlarmHostActor.SeverityToInt</c>
/// emits (Low≤250, Medium≤500, High≤750, Critical otherwise). Driven end-to-end through the enqueue.</summary>