fix(r2-10): DriverResilienceStatusChanged DPS contract

This commit is contained in:
Joseph Doherty
2026-07-13 10:39:18 -04:00
parent 0ba60db1e4
commit 2cb3f962b9
2 changed files with 36 additions and 1 deletions
@@ -5,7 +5,7 @@
{ "id": "T1", "subject": "Tracker: LastBreakerClosedUtc + IsBreakerOpen + RecordBreakerClose (Core, TDD in DriverResilienceStatusTrackerTests)", "status": "completed", "blockedBy": [] },
{ "id": "T2", "subject": "Builder: OnClosed records breaker-close on the tracker (TDD in DriverResiliencePipelineBuilderTests)", "status": "completed", "blockedBy": ["T1"] },
{ "id": "T3", "subject": "Invoker: successful Execute* resets ConsecutiveFailures (TDD in CapabilityInvokerTests)", "status": "completed", "blockedBy": ["T1"] },
{ "id": "T4", "subject": "Commons: DriverResilienceStatusChanged record + driver-resilience-status TopicName", "status": "pending", "blockedBy": [] },
{ "id": "T4", "subject": "Commons: DriverResilienceStatusChanged record + driver-resilience-status TopicName", "status": "completed", "blockedBy": [] },
{ "id": "T5", "subject": "Host: DriverResilienceStatusPublisherService (BuildMessages mapping + 5s DPS timer shell; TDD mapping in Host.IntegrationTests)", "status": "pending", "blockedBy": ["T1", "T4"] },
{ "id": "T6", "subject": "Host DI: register the publisher in AddOtOpcUaDriverFactories + ResilienceStatusReaderRegistrationTests wiring guard (tracker HAS a production reader)", "status": "pending", "blockedBy": ["T5"] },
{ "id": "T7", "subject": "AdminUI: IDriverResilienceStatusStore + InMemory impl + AddOtOpcUaDriverStatusServices registration (TDD mirroring DriverStatusSnapshotStoreTests)", "status": "pending", "blockedBy": ["T4"] },
@@ -0,0 +1,35 @@
namespace ZB.MOM.WW.OtOpcUa.Commons.Messages.Drivers;
/// <summary>
/// Snapshot of one driver instance's live resilience counters for a single target host,
/// published periodically to the <c>driver-resilience-status</c> DistributedPubSub topic by
/// <c>DriverResilienceStatusPublisherService</c> (Host, driver-role nodes) and consumed by the
/// AdminUI <c>DriverResilienceStatusBridge</c> → <c>IDriverResilienceStatusStore</c> →
/// resilience section of the driver status panel. Mirrors the <see cref="DriverHealthChanged"/>
/// flow one-for-one; a separate topic keeps the two feeds (event-driven health vs. periodic
/// resilience) decoupled.
/// </summary>
/// <param name="DriverInstanceId">Globally-unique driver instance ID (the panel filters on this alone).</param>
/// <param name="HostName">Target host the counters aggregate for (per-device breaker isolation key).</param>
/// <param name="BreakerOpen">Whether the circuit breaker is currently open for this (instance, host).</param>
/// <param name="ConsecutiveFailures">Consecutive pipeline failures — nonzero only during an active retry storm.</param>
/// <param name="CurrentInFlight">In-flight capability-call depth against this (instance, host).</param>
/// <param name="LastBreakerOpenUtc">UTC of the most recent breaker-open event; null if never.</param>
/// <param name="LastSampledUtc">UTC the tracker counters were last updated.</param>
/// <param name="PublishedUtc">UTC this snapshot was published (drives staleness detection in the panel).</param>
public sealed record DriverResilienceStatusChanged(
string DriverInstanceId,
string HostName,
bool BreakerOpen,
int ConsecutiveFailures,
int CurrentInFlight,
DateTime? LastBreakerOpenUtc,
DateTime LastSampledUtc,
DateTime PublishedUtc)
{
/// <summary>
/// DPS topic name. Both the Host publisher and the AdminUI bridge reference this single
/// constant on the contract so a rename can't silently desynchronise publisher and subscriber.
/// </summary>
public const string TopicName = "driver-resilience-status";
}