using Akka.Actor; using Akka.Cluster.Tools.PublishSubscribe; using ZB.MOM.WW.OtOpcUa.Commons.Messages.Drivers; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Runtime.Telemetry; namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers; /// /// Forwards transitions to the cluster-wide /// driver-health DistributedPubSub topic. Consumed by the AdminUI /// DriverStatusSignalRBridge. /// public sealed class AkkaDriverHealthPublisher : IDriverHealthPublisher { /// The DistributedPubSub topic name for driver-health snapshots — single source /// of truth on the message contract itself. public const string TopicName = DriverHealthChanged.TopicName; private readonly ActorSystem _system; private readonly ITelemetryLocalHub _hub; /// Initializes a new instance of . /// The Akka actor system used to resolve the DPS mediator. /// The node-local live-telemetry hub each snapshot is also emitted into (Phase 5). public AkkaDriverHealthPublisher(ActorSystem system, ITelemetryLocalHub hub) { _system = system; _hub = hub; } /// public void Publish(string clusterId, string driverInstanceId, DriverHealth health, int errorCount5Min) { var msg = new DriverHealthChanged( clusterId, driverInstanceId, health.State.ToString(), health.LastSuccessfulRead, health.LastError, errorCount5Min, DateTime.UtcNow); DistributedPubSub.Get(_system).Mediator.Tell(new Publish(TopicName, msg)); // Phase 5: fan the same snapshot into the node-local live-telemetry hub (no-op until a gRPC // client subscribes). The DPS publish above is unchanged — the hub is a strictly additive tap. _hub.Emit(new TelemetryItem.Health(msg)); } }