using Akka.Actor;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.OtOpcUa.Cluster;
using ZB.MOM.WW.OtOpcUa.Commons.Interfaces;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Fleet;
using ZB.MOM.WW.OtOpcUa.Commons.Types;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Clients;
///
/// backed by an Akka against
/// the target node's DriverHostActor at akka.tcp://otopcua@<host>:<port>/user/driver-host.
/// Sends ; expects a reply.
///
/// On timeout or any other failure (peer down, GetDiagnostics handler missing) returns an
/// empty snapshot so the UI degrades to "no data" instead of throwing.
///
public sealed class FleetDiagnosticsClient : IFleetDiagnosticsClient
{
private static readonly TimeSpan AskTimeout = TimeSpan.FromSeconds(3);
private readonly ActorSystem _system;
private readonly string _systemName;
/// Initializes a new FleetDiagnosticsClient with the given actor system and cluster options.
/// The Akka actor system.
/// Cluster configuration options.
public FleetDiagnosticsClient(ActorSystem system, IOptions options)
{
_system = system;
_systemName = options.Value.SystemName;
}
/// Gets diagnostics for a cluster node.
/// The node identifier to query.
/// Cancellation token.
/// Diagnostics snapshot for the node, or an empty snapshot if the query fails.
public async Task GetDiagnosticsAsync(NodeId nodeId, CancellationToken ct)
{
var selection = _system.ActorSelection($"akka.tcp://{_systemName}@{nodeId.Value}/user/driver-host");
try
{
using var linked = CancellationTokenSource.CreateLinkedTokenSource(ct);
linked.CancelAfter(AskTimeout);
return await selection.Ask(
new GetDiagnostics(CorrelationId.NewId()), AskTimeout, linked.Token);
}
catch (Exception)
{
return new NodeDiagnosticsSnapshot(
nodeId,
CurrentRevision: null,
Drivers: Array.Empty(),
AsOfUtc: DateTime.UtcNow);
}
}
}