feat(runtime): VirtualTagActor skeleton (engine wiring tracked as F8)
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
using Akka.Actor;
|
||||
using Akka.Event;
|
||||
using ZB.MOM.WW.OtOpcUa.Commons.Types;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Runtime.VirtualTags;
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a single virtual-tag expression. Receives dependency-tag updates, recomputes the
|
||||
/// expression, and publishes the result to <c>OpcUaPublishActor</c>.
|
||||
///
|
||||
/// Engine wiring (compile expression via <c>VirtualTagEngine</c>, manage subscriptions,
|
||||
/// emit <c>AttributeValueUpdate</c>) is staged for follow-up F8. This skeleton compiles + has
|
||||
/// a basic message contract so DriverHostActor can spawn it as a child.
|
||||
/// </summary>
|
||||
public sealed class VirtualTagActor : ReceiveActor
|
||||
{
|
||||
public sealed record DependencyValueChanged(string TagId, object? Value, DateTime TimestampUtc);
|
||||
public sealed record EvaluationResult(string VirtualTagId, object? Value, DateTime TimestampUtc, CorrelationId Correlation);
|
||||
|
||||
private readonly string _virtualTagId;
|
||||
private readonly string _expression;
|
||||
private readonly ILoggingAdapter _log = Context.GetLogger();
|
||||
private readonly Dictionary<string, object?> _dependencies = new(StringComparer.Ordinal);
|
||||
|
||||
public static Props Props(string virtualTagId, string expression) =>
|
||||
Akka.Actor.Props.Create(() => new VirtualTagActor(virtualTagId, expression));
|
||||
|
||||
public VirtualTagActor(string virtualTagId, string expression)
|
||||
{
|
||||
_virtualTagId = virtualTagId;
|
||||
_expression = expression;
|
||||
|
||||
Receive<DependencyValueChanged>(msg =>
|
||||
{
|
||||
_dependencies[msg.TagId] = msg.Value;
|
||||
// Engine wiring (F8): VirtualTagEngine.Evaluate(_expression, _dependencies) → publish.
|
||||
_log.Debug("VirtualTag {Id}: dependency {Tag}={Value} buffered (eval staged for F8)",
|
||||
_virtualTagId, msg.TagId, msg.Value);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Akka.Actor;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Tests.Harness;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.VirtualTags;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.VirtualTags;
|
||||
|
||||
public sealed class VirtualTagActorTests : RuntimeActorTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void DependencyValueChanged_is_accepted_and_actor_stays_alive()
|
||||
{
|
||||
var actor = Sys.ActorOf(VirtualTagActor.Props("vt-1", "a + b"));
|
||||
Watch(actor);
|
||||
actor.Tell(new VirtualTagActor.DependencyValueChanged("tag-a", 10, DateTime.UtcNow));
|
||||
actor.Tell(new VirtualTagActor.DependencyValueChanged("tag-b", 20, DateTime.UtcNow));
|
||||
|
||||
// No crash, no termination.
|
||||
ExpectNoMsg(TimeSpan.FromMilliseconds(200));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user