feat(scripted-alarms): spawn + apply ScriptedAlarmHostActor in DriverHostActor (T10)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using Akka.Actor;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Shouldly;
|
||||
@@ -7,6 +8,7 @@ using ZB.MOM.WW.OtOpcUa.Commons.Types;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.ScriptedAlarms;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Tests.Harness;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
|
||||
@@ -126,6 +128,84 @@ public sealed class DriverHostActorTests : RuntimeActorTestBase
|
||||
.Status.ShouldBe(NodeDeploymentStatus.Applied);
|
||||
}
|
||||
|
||||
/// <summary>Fresh apply: dispatching a deployment whose artifact carries one Equipment
|
||||
/// ScriptedAlarm forwards a <see cref="ScriptedAlarmHostActor.ApplyScriptedAlarms"/> carrying that
|
||||
/// plan to the injected ScriptedAlarm host (via the <c>scriptedAlarmHostOverride</c> seam, mirroring
|
||||
/// the VirtualTag-host wiring).</summary>
|
||||
[Fact]
|
||||
public void Apply_forwards_EquipmentScriptedAlarms_to_scripted_alarm_host()
|
||||
{
|
||||
var db = NewInMemoryDbFactory();
|
||||
var deploymentId = SeedDeploymentWithScriptedAlarm(db, RevA);
|
||||
|
||||
var coordinator = CreateTestProbe();
|
||||
var alarmHost = CreateTestProbe();
|
||||
var actor = Sys.ActorOf(DriverHostActor.Props(
|
||||
db, TestNode, coordinator.Ref,
|
||||
localRoles: new HashSet<string> { "driver" },
|
||||
scriptedAlarmHostOverride: alarmHost.Ref));
|
||||
|
||||
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
|
||||
|
||||
coordinator.ExpectMsg<ApplyAck>(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
|
||||
|
||||
var apply = alarmHost.ExpectMsg<ScriptedAlarmHostActor.ApplyScriptedAlarms>(TimeSpan.FromSeconds(5));
|
||||
var plan = apply.Plans.ShouldHaveSingleItem();
|
||||
plan.ScriptedAlarmId.ShouldBe("al-1");
|
||||
plan.EquipmentId.ShouldBe("eq-1");
|
||||
plan.Name.ShouldBe("Overheat");
|
||||
plan.PredicateSource.ShouldContain("ctx.GetTag");
|
||||
}
|
||||
|
||||
private static DeploymentId SeedDeploymentWithScriptedAlarm(
|
||||
IDbContextFactory<OtOpcUaConfigDbContext> db, RevisionHash rev)
|
||||
{
|
||||
// Artifact carries a ScriptedAlarm joined (by PredicateScriptId) to its predicate Script —
|
||||
// the same shape ConfigComposer emits and DeploymentArtifact.ParseComposition decodes into
|
||||
// composition.EquipmentScriptedAlarms.
|
||||
var artifact = JsonSerializer.SerializeToUtf8Bytes(new
|
||||
{
|
||||
Scripts = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
ScriptId = "scr-1",
|
||||
SourceCode = "return System.Convert.ToDouble(ctx.GetTag(\"Mach1.Temp\").Value) > 80;",
|
||||
},
|
||||
},
|
||||
ScriptedAlarms = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
ScriptedAlarmId = "al-1",
|
||||
EquipmentId = "eq-1",
|
||||
Name = "Overheat",
|
||||
AlarmType = "LimitAlarm",
|
||||
Severity = 700,
|
||||
MessageTemplate = "Machine 1 hot",
|
||||
PredicateScriptId = "scr-1",
|
||||
HistorizeToAveva = true,
|
||||
Retain = true,
|
||||
Enabled = true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
var id = DeploymentId.NewId();
|
||||
using var ctx = db.CreateDbContext();
|
||||
ctx.Deployments.Add(new Configuration.Entities.Deployment
|
||||
{
|
||||
DeploymentId = id.Value,
|
||||
RevisionHash = rev.Value,
|
||||
Status = DeploymentStatus.Sealed,
|
||||
CreatedBy = "test",
|
||||
SealedAtUtc = DateTime.UtcNow,
|
||||
ArtifactBlob = artifact,
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
return id;
|
||||
}
|
||||
|
||||
private static DeploymentId SeedDeployment(
|
||||
IDbContextFactory<OtOpcUaConfigDbContext> db,
|
||||
RevisionHash rev,
|
||||
|
||||
Reference in New Issue
Block a user