using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Health;
///
/// Pushes the synthetic top-level transport-health entry into the
/// . Each driver instance has one entry under its
/// MxAccess.ClientName reflecting the gateway transport state — useful for
/// dashboards that want a single "Galaxy is up" signal independent of any individual
/// platform's ScanState.
///
///
/// The eventual production source for this signal is the gateway's StreamSessionHealth
/// RPC (mxaccessgw issue gw-6). Until that ships, the driver-side reconnect supervisor
/// (PR 4.5) calls on transport state transitions:
/// when the gw session re-Registers,
/// when the supervisor moves to TransportLost. The forwarder is intentionally
/// stateless beyond the cached client name + last-pushed value so the supervisor can
/// drive it without any back-pressure plumbing.
///
public sealed class HostConnectivityForwarder : IDisposable
{
private readonly string _clientName;
private readonly HostStatusAggregator _aggregator;
private readonly ILogger _logger;
private bool _disposed;
/// Initializes a new instance of HostConnectivityForwarder with the given client name, aggregator, and optional logger.
/// The client name for the MxAccess connection.
/// The host status aggregator to push connectivity state to.
/// The optional logger for diagnostic messages.
public HostConnectivityForwarder(string clientName, HostStatusAggregator aggregator, ILogger? logger = null)
{
ArgumentException.ThrowIfNullOrWhiteSpace(clientName);
_clientName = clientName;
_aggregator = aggregator ?? throw new ArgumentNullException(nameof(aggregator));
_logger = logger ?? NullLogger.Instance;
}
///
/// Push a transport state into the aggregator. Idempotent at the aggregator layer —
/// repeated calls with the same state don't fan out duplicate transitions.
///
/// The host connectivity state to push.
public void SetTransport(HostState state)
{
ObjectDisposedException.ThrowIf(_disposed, this);
var status = new HostConnectivityStatus(_clientName, state, DateTime.UtcNow);
_aggregator.Update(status);
_logger.LogDebug(
"GalaxyDriver transport state for {ClientName}: {State}",
_clientName, state);
}
/// Disposes the forwarder and marks it as disposed.
public void Dispose()
{
// No-op today; reserved for the eventual gw-6 StreamSessionHealth consumer that
// will own a long-running task this method tears down.
_disposed = true;
}
}