docs(xmldoc): fill missing XML docs + strip tracking-ID comments across src
v2-ci / build (push) Failing after 41s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Adds <summary>/<param>/<returns>/<inheritdoc> where missing and removes
project bookkeeping IDs (task/tracking refs) from shipped code comments,
so the docs read cleanly and CommentChecker is quiet except for known
false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc).
Doc/comment-only; no logic changed; solution builds clean.
This commit is contained in:
Joseph Doherty
2026-07-07 12:38:39 -04:00
parent 384dbd7d36
commit 9cad9ed0fc
375 changed files with 1899 additions and 2493 deletions
@@ -8,7 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Resilience;
/// <see cref="IAlarmSource.AcknowledgeAsync"/>) through <see cref="CapabilityInvoker"/> so the
/// Phase 6.1 resilience pipeline runs — retry semantics match
/// <see cref="DriverCapability.AlarmSubscribe"/> (retries by default) and
/// <see cref="DriverCapability.AlarmAcknowledge"/> (does NOT retry per decision #143).
/// <see cref="DriverCapability.AlarmAcknowledge"/> (does NOT retry).
/// </summary>
/// <remarks>
/// <para>Multi-host dispatch: when the driver implements <see cref="IPerCallHostResolver"/>,
@@ -59,6 +59,7 @@ public sealed class AlarmSurfaceInvoker
/// </summary>
/// <param name="sourceNodeIds">The source node IDs to subscribe to.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>One subscription handle per resolved host.</returns>
public async Task<IReadOnlyList<IAlarmSubscriptionHandle>> SubscribeAsync(
IReadOnlyList<string> sourceNodeIds,
CancellationToken cancellationToken)
@@ -89,6 +90,7 @@ public sealed class AlarmSurfaceInvoker
/// </summary>
/// <param name="handle">The subscription handle to unsubscribe.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public ValueTask UnsubscribeAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(handle);
@@ -105,11 +107,12 @@ public sealed class AlarmSurfaceInvoker
/// <summary>
/// Acknowledge alarms. Fans out by resolved host; each host's batch runs through the
/// AlarmAcknowledge pipeline (no-retry per decision #143 — an alarm-ack is not idempotent
/// AlarmAcknowledge pipeline (no-retry — an alarm-ack is not idempotent
/// at the plant-floor acknowledgement level even if the OPC UA spec permits re-issue).
/// </summary>
/// <param name="acknowledgements">The alarm acknowledgement requests.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async Task AcknowledgeAsync(
IReadOnlyList<AlarmAcknowledgeRequest> acknowledgements,
CancellationToken cancellationToken)
@@ -161,7 +164,7 @@ public sealed class AlarmSurfaceInvoker
public IAlarmSubscriptionHandle Inner { get; } = inner;
/// <summary>Gets the resolved host name.</summary>
public string Host { get; } = host;
/// <summary>Gets the diagnostic ID from the inner handle.</summary>
/// <inheritdoc />
public string DiagnosticId => Inner.DiagnosticId;
}
}
@@ -10,7 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Resilience;
/// is process-singleton so all invokers share its cache.
/// </summary>
/// <remarks>
/// Per <c>docs/v2/plan.md</c> decisions #143-144 and Phase 6.1 Stream A.3. The server's dispatch
/// The server's dispatch
/// layer routes every capability call (<c>IReadable.ReadAsync</c>, <c>IWritable.WriteAsync</c>,
/// <c>ITagDiscovery.DiscoverAsync</c>, <c>ISubscribable.SubscribeAsync/UnsubscribeAsync</c>,
/// <c>IHostConnectivityProbe</c> probe loop, <c>IAlarmSource.SubscribeAlarmsAsync/AcknowledgeAsync</c>,
@@ -58,6 +58,7 @@ public sealed class CapabilityInvoker
/// <param name="hostName">The host name for logging and status tracking.</param>
/// <param name="callSite">The async function to execute.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
/// <returns>The result of the underlying driver call.</returns>
public async ValueTask<TResult> ExecuteAsync<TResult>(
DriverCapability capability,
string hostName,
@@ -86,6 +87,7 @@ public sealed class CapabilityInvoker
/// <param name="hostName">The host name for logging and status tracking.</param>
/// <param name="callSite">The async function to execute.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public async ValueTask ExecuteAsync(
DriverCapability capability,
string hostName,
@@ -112,8 +114,8 @@ public sealed class CapabilityInvoker
/// <summary>
/// Execute a <see cref="DriverCapability.Write"/> call honoring <see cref="WriteIdempotentAttribute"/>
/// semantics — if <paramref name="isIdempotent"/> is <c>false</c>, retries are disabled regardless
/// of the tag-level configuration (the pipeline for a non-idempotent write never retries per
/// decisions #44-45). If <c>true</c>, the call runs through the capability's pipeline which may
/// of the tag-level configuration (the pipeline for a non-idempotent write never retries).
/// If <c>true</c>, the call runs through the capability's pipeline which may
/// retry when the tier configuration permits.
/// </summary>
/// <typeparam name="TResult">Return type of the underlying driver call.</typeparam>
@@ -121,6 +123,7 @@ public sealed class CapabilityInvoker
/// <param name="isIdempotent">Whether the write operation is idempotent.</param>
/// <param name="callSite">The async function to execute.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
/// <returns>The result of the underlying driver write call.</returns>
public async ValueTask<TResult> ExecuteWriteAsync<TResult>(
string hostName,
bool isIdempotent,
@@ -5,7 +5,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Resilience;
/// <summary>
/// Per-tier × per-capability resilience policy configuration for a driver instance.
/// Bound from <c>DriverInstance.ResilienceConfig</c> JSON (nullable column; null = tier defaults).
/// Per <c>docs/v2/plan.md</c> decisions #143 and #144.
/// Per <c>docs/v2/plan.md</c>.
/// </summary>
public sealed record DriverResilienceOptions
{
@@ -34,7 +34,7 @@ public sealed record DriverResilienceOptions
/// indefinitely unless a memory breach or operator action triggers a recycle. Only
/// respected for <see cref="DriverTier.C"/>; Tier A/B recycle would tear down every
/// OPC UA session, so the loader ignores non-null values for those tiers + logs a
/// warning (per decisions #74 / #145).
/// warning.
/// </summary>
public int? RecycleIntervalSeconds { get; init; }
@@ -68,7 +68,7 @@ public sealed record DriverResilienceOptions
}
/// <summary>
/// Per-tier per-capability default policy table, per decisions #143-144 and the Phase 6.1
/// Per-tier per-capability default policy table, per the Phase 6.1
/// Stream A.2 specification. Retries skipped on <see cref="DriverCapability.Write"/> and
/// <see cref="DriverCapability.AlarmAcknowledge"/> regardless of tier.
/// </summary>
@@ -119,6 +119,6 @@ public sealed record DriverResilienceOptions
/// <param name="RetryCount">Number of retry attempts after the first failure; zero = no retry.</param>
/// <param name="BreakerFailureThreshold">
/// Consecutive-failure count that opens the circuit breaker; zero = no breaker
/// (Tier C uses the supervisor's process-level breaker instead, per decision #68).
/// (Tier C uses the supervisor's process-level breaker instead).
/// </param>
public sealed record CapabilityPolicy(int TimeoutSeconds, int RetryCount, int BreakerFailureThreshold);
@@ -50,6 +50,7 @@ public static class DriverResilienceOptionsParser
/// <param name="tier">The driver tier for default resilience options.</param>
/// <param name="resilienceConfigJson">The optional JSON configuration string to parse.</param>
/// <param name="parseDiagnostic">An out parameter containing diagnostic information if parsing fails.</param>
/// <returns>The effective <see cref="DriverResilienceOptions"/>, layering any parsed overrides on top of the tier defaults.</returns>
public static DriverResilienceOptions ParseOrDefaults(
DriverTier tier,
string? resilienceConfigJson,
@@ -96,7 +97,7 @@ public static class DriverResilienceOptionsParser
// Scheduled recycle is Tier C only — reject a configured interval on Tier A/B as a
// misconfiguration surface rather than silently honouring it (recycling an in-process
// driver would kill every OPC UA session + every co-hosted driver, per decision #74).
// driver would kill every OPC UA session + every co-hosted driver).
int? recycleIntervalSeconds = null;
if (shape.RecycleIntervalSeconds is int secs)
{
@@ -13,7 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Resilience;
/// driver cannot open the circuit breaker for healthy sibling hosts.
/// </summary>
/// <remarks>
/// Per <c>docs/v2/plan.md</c> decision #144 (per-device isolation). Composition from outside-in:
/// Per-device isolation. Composition from outside-in:
/// <b>Timeout → Retry (when capability permits) → Circuit Breaker (when tier permits) → Bulkhead</b>.
///
/// <para>Pipeline resolution is lock-free on the hot path: the inner
@@ -54,6 +54,7 @@ public sealed class DriverResiliencePipelineBuilder
/// </param>
/// <param name="capability">Which capability surface is being called.</param>
/// <param name="options">Per-driver-instance options (tier + per-capability overrides).</param>
/// <returns>The cached or newly built resilience pipeline for the key.</returns>
public ResiliencePipeline GetOrCreate(
string driverInstanceId,
string hostName,
@@ -128,10 +128,12 @@ public sealed class DriverResilienceStatusTracker
/// <summary>Snapshot of a specific (instance, host) pair; null if no counters recorded yet.</summary>
/// <param name="driverInstanceId">The driver instance identifier.</param>
/// <param name="hostName">The host name.</param>
/// <returns>The current resilience status snapshot, or null if no counters have been recorded for this pair.</returns>
public ResilienceStatusSnapshot? TryGet(string driverInstanceId, string hostName) =>
_status.TryGetValue(new StatusKey(driverInstanceId, hostName), out var snapshot) ? snapshot : null;
/// <summary>Copy of every currently-tracked (instance, host, snapshot) triple. Safe under concurrent writes.</summary>
/// <returns>A snapshot list of all tracked (driver instance, host, resilience snapshot) triples.</returns>
public IReadOnlyList<(string DriverInstanceId, string HostName, ResilienceStatusSnapshot Snapshot)> Snapshot() =>
_status.Select(kvp => (kvp.Key.DriverInstanceId, kvp.Key.HostName, kvp.Value)).ToList();