using Akka.Actor; using Akka.Cluster.Tools.PublishSubscribe; using Akka.Event; using Microsoft.AspNetCore.SignalR; using ZB.MOM.WW.OtOpcUa.Commons.Messages.Alerts; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs; /// /// Akka actor that subscribes to the alerts DistributedPubSub topic and forwards each /// to every SignalR client connected to . /// Mirrors FleetStatusSignalRBridge's design — one bridge per admin node, hub fan-out is /// per-node, no cluster-singleton needed. /// public sealed class AlertSignalRBridge : ReceiveActor { public const string TopicName = "alerts"; private readonly IHubContext _hub; private readonly ILoggingAdapter _log = Context.GetLogger(); public static Props Props(IHubContext hub) => Akka.Actor.Props.Create(() => new AlertSignalRBridge(hub)); public AlertSignalRBridge(IHubContext hub) { _hub = hub; ReceiveAsync(ForwardAsync); Receive(_ => { /* DPS confirmation */ }); } protected override void PreStart() => DistributedPubSub.Get(Context.System).Mediator.Tell(new Subscribe(TopicName, Self)); private async Task ForwardAsync(AlarmTransitionEvent msg) { try { await _hub.Clients.All.SendAsync(AlertHub.MethodName, msg); } catch (Exception ex) { _log.Warning(ex, "AlertSignalRBridge: SignalR push failed for {AlarmId}", msg.AlarmId); } } }