using Akka.Actor;
using Akka.Cluster.Tools.PublishSubscribe;
using Akka.Event;
using Microsoft.AspNetCore.SignalR;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Logging;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
///
/// Akka actor that subscribes to the script-logs DistributedPubSub topic and forwards each
/// to every SignalR client connected to .
///
public sealed class ScriptLogSignalRBridge : ReceiveActor
{
public const string TopicName = "script-logs";
private readonly IHubContext _hub;
private readonly IInProcessBroadcaster _broadcaster;
private readonly ILoggingAdapter _log = Context.GetLogger();
/// Creates a Props instance for the ScriptLogSignalRBridge.
/// The SignalR hub context for sending messages to clients.
/// In-process fan-out read directly by the Blazor Server Script log page.
public static Props Props(IHubContext hub, IInProcessBroadcaster broadcaster) =>
Akka.Actor.Props.Create(() => new ScriptLogSignalRBridge(hub, broadcaster));
/// Initializes a new instance of the class.
/// The SignalR hub context for sending messages to clients.
/// In-process fan-out read directly by the Blazor Server Script log page.
public ScriptLogSignalRBridge(IHubContext hub, IInProcessBroadcaster broadcaster)
{
_hub = hub;
_broadcaster = broadcaster;
ReceiveAsync(ForwardAsync);
Receive(_ => { /* DPS confirmation */ });
}
///
protected override void PreStart() =>
DistributedPubSub.Get(Context.System).Mediator.Tell(new Subscribe(TopicName, Self));
private async Task ForwardAsync(ScriptLogEntry msg)
{
// In-process fan-out first — this is what the Blazor Server Script log page reads. The hub
// push is kept for any out-of-process (e.g. WASM) SignalR client.
_broadcaster.Publish(msg);
try
{
await _hub.Clients.All.SendAsync(ScriptLogHub.MethodName, msg);
}
catch (Exception ex)
{
_log.Warning(ex, "ScriptLogSignalRBridge: SignalR push failed for {ScriptId}", msg.ScriptId);
}
}
}