c2bdb7d5de
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
77 lines
3.7 KiB
C#
77 lines
3.7 KiB
C#
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
/// <summary>
|
|
/// Sink for driver-health state-change notifications. The runtime DI wires the
|
|
/// Akka-DistributedPubSub-backed implementation; tests and dev-stub paths use
|
|
/// <see cref="NullDriverHealthPublisher"/> to opt out without changing call sites.
|
|
/// </summary>
|
|
public interface IDriverHealthPublisher
|
|
{
|
|
/// <summary>
|
|
/// Publishes a health snapshot for one driver instance. Implementations must be
|
|
/// non-blocking and tolerant of being called from any thread.
|
|
/// </summary>
|
|
/// <param name="clusterId">The cluster the driver instance belongs to.</param>
|
|
/// <param name="driverInstanceId">The driver instance the snapshot describes.</param>
|
|
/// <param name="health">The current health snapshot.</param>
|
|
/// <param name="errorCount5Min">The number of errors observed in the trailing 5-minute window.</param>
|
|
/// <param name="rediscoveryNeededUtc">
|
|
/// When the driver last raised <see cref="IRediscoverable.OnRediscoveryNeeded"/>, or null if never
|
|
/// (or if it is not an <see cref="IRediscoverable"/>). Advisory: it prompts an operator to
|
|
/// re-browse, and never rebuilds the served address space.
|
|
/// </param>
|
|
/// <param name="rediscoveryReason">The driver-supplied reason from that event; null when
|
|
/// <paramref name="rediscoveryNeededUtc"/> is null.</param>
|
|
/// <param name="hostStatuses">
|
|
/// Per-host connectivity from <see cref="IHostConnectivityProbe.GetHostStatuses"/>, or null when the
|
|
/// driver is not an <see cref="IHostConnectivityProbe"/>. Lets a multi-device driver (a FOCAS or
|
|
/// AbLegacy instance owning several PLCs) surface ONE unreachable device that would otherwise be
|
|
/// invisible behind an aggregate-Healthy driver row.
|
|
/// </param>
|
|
/// <param name="skippedTags">
|
|
/// Authored tags the driver could not build into its poll table, from
|
|
/// <see cref="ISkippedTagReporter.GetSkippedTags"/>; null when the driver is not an
|
|
/// <see cref="ISkippedTagReporter"/>. Contradicts the "Healthy, 0 errors, reads advancing" reading
|
|
/// of a driver that is in fact ignoring part or all of its configuration (Gitea #541).
|
|
/// </param>
|
|
/// <param name="diagnostics">
|
|
/// Bounded driver diagnostics from <see cref="IDriverDiagnostics.GetDiagnostics"/>; null when the
|
|
/// driver is not an <see cref="IDriverDiagnostics"/> (Gitea #640).
|
|
/// </param>
|
|
void Publish(
|
|
string clusterId,
|
|
string driverInstanceId,
|
|
DriverHealth health,
|
|
int errorCount5Min,
|
|
DateTime? rediscoveryNeededUtc = null,
|
|
string? rediscoveryReason = null,
|
|
IReadOnlyList<HostConnectivityStatus>? hostStatuses = null,
|
|
SkippedTagReport? skippedTags = null,
|
|
IReadOnlyDictionary<string, string>? diagnostics = null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Drop-in no-op for tests and dev-stub paths. Production wires the Akka-backed
|
|
/// implementation in the Runtime project.
|
|
/// </summary>
|
|
public sealed class NullDriverHealthPublisher : IDriverHealthPublisher
|
|
{
|
|
/// <summary>Singleton instance.</summary>
|
|
public static readonly NullDriverHealthPublisher Instance = new();
|
|
|
|
private NullDriverHealthPublisher() { }
|
|
|
|
/// <inheritdoc />
|
|
public void Publish(
|
|
string clusterId,
|
|
string driverInstanceId,
|
|
DriverHealth health,
|
|
int errorCount5Min,
|
|
DateTime? rediscoveryNeededUtc = null,
|
|
string? rediscoveryReason = null,
|
|
IReadOnlyList<HostConnectivityStatus>? hostStatuses = null,
|
|
SkippedTagReport? skippedTags = null,
|
|
IReadOnlyDictionary<string, string>? diagnostics = null)
|
|
{ /* no-op */ }
|
|
}
|