docs: fill missing XML docs and strip tracking IDs from src comments
Clears CommentChecker findings in src/ (3,280 -> 209, the remainder being false positives like PLC-5/IEEE-754/M0.0) by adding missing summaries/params/returns, normalising inheritdoc usage, and removing Gitea/review tracking IDs while keeping the rationale they annotated. Comment-only: comment-stripped sources are identical to the parent commit.
This commit is contained in:
@@ -28,7 +28,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Calculation;
|
||||
/// at least once, and equal results are deduped) and/or on a timer (one timer per interval group).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>Where scripts run (Driver.Calculation-005).</b> <see cref="OnDependencyValue"/> is called
|
||||
/// <b>Where scripts run.</b> <see cref="OnDependencyValue"/> is called
|
||||
/// directly and synchronously by <c>DependencyConsumerMuxAdapter</c> — on an Akka actor's own
|
||||
/// dispatcher thread — so it does no evaluation itself: it records the value, <i>prepares</i> the
|
||||
/// affected tags (definition + dependency snapshot, taken at trigger time) and hands them to a
|
||||
@@ -47,7 +47,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Calculation;
|
||||
/// </summary>
|
||||
public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscribable, IReadable, ISkippedTagReporter, IDisposable
|
||||
{
|
||||
/// <summary>Authored tags this driver could not build into its calc table (Gitea #541). A raw tag with
|
||||
/// <summary>Authored tags this driver could not build into its calc table. A raw tag with
|
||||
/// no <c>scriptId</c> is not a calc tag and computes nothing.</summary>
|
||||
private readonly SkippedTagLedger _skippedTags = new();
|
||||
|
||||
@@ -79,10 +79,9 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
|
||||
// Live evaluation state. Guarded by _lock: OnDependencyValue (the mux actor's thread), timer ticks
|
||||
// and the evaluation pump (pool threads) all touch it, so state mutation is serialized. _lock is a
|
||||
// SHORT-HELD state lock — it is taken for dictionary work only and is NEVER held across a script run
|
||||
// (Driver.Calculation-005).
|
||||
// SHORT-HELD state lock — it is taken for dictionary work only and is NEVER held across a script run.
|
||||
private readonly object _lock = new();
|
||||
// Dependency SNAPSHOTS, not bare values (archreview 05/STAB-19): the status code is what tells a
|
||||
// Dependency SNAPSHOTS, not bare values: the status code is what tells a
|
||||
// comms-lost input apart from a genuine Good null, and storing values only is what let this driver
|
||||
// compute a Good output from a dead source.
|
||||
private readonly Dictionary<string, DataValueSnapshot> _depValues = new(StringComparer.Ordinal);
|
||||
@@ -273,7 +272,9 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
/// <c>CalculationDriverConfigDto</c>.</summary>
|
||||
private sealed class ReinitConfigDto
|
||||
{
|
||||
/// <summary>The raw tag entries carried by the re-initialisation config.</summary>
|
||||
public List<RawTagEntry>? RawTags { get; init; }
|
||||
/// <summary>The optional evaluation timeout in milliseconds; ignored on re-initialisation.</summary>
|
||||
public int? RunTimeoutMs { get; init; }
|
||||
}
|
||||
|
||||
@@ -285,14 +286,12 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
/// <inheritdoc />
|
||||
public string DriverType => DriverTypeNames.Calculation;
|
||||
|
||||
// InitializeAsync takes a config document and the IDriver contract is that the driver serves it
|
||||
// (the runtime's mid-connect adoption path was deleted) - so it adopts a config carrying a real
|
||||
// body (the convention every other driver follows), and disposes any running timer scheduler before
|
||||
// arming a fresh one (re-initialise without teardown must not leak). A "{}" / empty document keeps
|
||||
// the constructor-supplied tags, as unit tests rely on.
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// #664: <c>InitializeAsync</c> takes a config document and the <see cref="IDriver"/> contract is that the
|
||||
/// driver serves it (the runtime's mid-connect adoption path was deleted in #665) — so it adopts a config carrying a
|
||||
/// real body (the #516 convention every other driver follows), and disposes any running timer scheduler
|
||||
/// before arming a fresh one (#630: re-initialise without teardown must not leak). A <c>"{}"</c> / empty
|
||||
/// document keeps the constructor-supplied tags, as unit tests rely on.
|
||||
/// </remarks>
|
||||
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
||||
{
|
||||
StopTimers();
|
||||
@@ -310,7 +309,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
{
|
||||
// An in-place config change: re-bind the new config and REBUILD the tag table + dependency-ref set, so
|
||||
// added tags compute, removed tags stop publishing and edited scripts serve the new result. The runtime
|
||||
// itself applies a DriverConfig change by respawning (#516/#665), where a fresh driver registers its
|
||||
// itself applies a DriverConfig change by respawning, where a fresh driver registers its
|
||||
// new dependency refs on construction; this path keeps the IDriver contract honest for any caller.
|
||||
StopTimers();
|
||||
AdoptConfig(driverConfigJson);
|
||||
@@ -330,19 +329,15 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current health, derived from the driver's own lifecycle state.
|
||||
/// <para><b>Gitea #517.</b> This used to return a hard-coded <see cref="DriverState.Healthy"/> that
|
||||
/// consulted nothing. That made it the fleet's one driver whose <c>GetHealth()</c> reported Healthy
|
||||
/// <em>with its timers stopped</em> — not as a race window, but permanently and deterministically:
|
||||
/// before <see cref="InitializeAsync"/>, after <see cref="ShutdownAsync"/>, and after
|
||||
/// <see cref="Dispose"/>. Every other driver reads a <c>_health</c> field that shutdown lands on
|
||||
/// <see cref="DriverState.Unknown"/>.</para>
|
||||
/// <para>There is no transport to be Degraded about — this driver computes from the dependency mux,
|
||||
/// so its only meaningful states are "running" and "not running". <c>_running</c> is the flag the
|
||||
/// compute paths themselves gate on, which is what makes it the honest input here.</para>
|
||||
/// </summary>
|
||||
/// <returns>Healthy while running; otherwise Unknown, retaining the last compute time.</returns>
|
||||
// Current health, derived from the driver's own lifecycle state: Healthy while running; otherwise
|
||||
// Unknown, retaining the last compute time. Health is never a hard-coded Healthy - a driver whose
|
||||
// timers are stopped (before InitializeAsync, after ShutdownAsync, after Dispose) must not report
|
||||
// Healthy, matching every other driver, whose _health field lands on Unknown at shutdown.
|
||||
//
|
||||
// There is no transport to be Degraded about - this driver computes from the dependency mux, so its
|
||||
// only meaningful states are "running" and "not running". _running is the flag the compute paths
|
||||
// themselves gate on, which is what makes it the honest input here.
|
||||
/// <inheritdoc />
|
||||
public DriverHealth GetHealth() => _running
|
||||
? new DriverHealth(DriverState.Healthy, _lastComputeUtc, null)
|
||||
: new DriverHealth(DriverState.Unknown, _lastComputeUtc, null);
|
||||
@@ -363,7 +358,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
_arrivedDeps.Add(rawPath);
|
||||
if (!_changeDependents.TryGetValue(rawPath, out var dependents) || dependents.Count == 0) return;
|
||||
|
||||
// QUEUE each change-triggered dependent — never evaluate here (Driver.Calculation-005). This
|
||||
// QUEUE each change-triggered dependent — never evaluate here. This
|
||||
// runs on the caller's thread, which for the live path is the Akka dispatcher thread of
|
||||
// Runtime's DependencyConsumerMuxAdapter, and a script run is bounded only by RunTimeout.
|
||||
// Everything under this lock is dictionary work; the script runs on the pump.
|
||||
@@ -426,7 +421,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
return new DataValueSnapshot(null, StatusBadWaitingForInitialData, null, now);
|
||||
// Exactly what the subscriber was last told — including a propagated input sub-code. Deriving
|
||||
// it from a two-state flag here would make a read disagree with the subscription over the
|
||||
// same node (05/STAB-19).
|
||||
// same node.
|
||||
var status = st.LastPublishedStatus;
|
||||
return new DataValueSnapshot(st.LastValue, status, st.LastTimestampUtc, st.LastTimestampUtc);
|
||||
}
|
||||
@@ -484,7 +479,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
if (_depValues.TryGetValue(dep, out var v)) deps[dep] = v;
|
||||
|
||||
// Worst-of-input, computed from the SAME snapshot the evaluation will use, so the status
|
||||
// published can never disagree with the values it was derived from (05/STAB-19).
|
||||
// published can never disagree with the values it was derived from.
|
||||
var worst = InputQuality.WorstOf(def.DependencyRefs.Select(r => deps.GetValueOrDefault(r)));
|
||||
return new PendingEvaluation(def, deps, timestampUtc, worst);
|
||||
}
|
||||
@@ -556,7 +551,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
{
|
||||
var def = pending.Definition;
|
||||
|
||||
// HOLD ON BAD (05/STAB-19, matching ScriptedAlarmEngine's AreInputsReady): a Bad input is not
|
||||
// HOLD ON BAD (matching ScriptedAlarmEngine's AreInputsReady): a Bad input is not
|
||||
// usable, so the script does NOT run — which removes the "(double)ctx.GetTag(x).Value threw"
|
||||
// storm at its source rather than catching it downstream — and the tag reports the input's own
|
||||
// sub-code. Uncertain IS usable: the script runs and the output inherits the Uncertain code.
|
||||
@@ -576,7 +571,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
}
|
||||
|
||||
// Snapshots, not bare values: the script's ctx.GetTag(path).StatusCode / .SourceTimestampUtc are
|
||||
// then the input's real ones rather than a fabricated Good stamped at evaluation time (05/STAB-19).
|
||||
// then the input's real ones rather than a fabricated Good stamped at evaluation time.
|
||||
var result = _evaluator.Evaluate(def.RawPath, def.ScriptSource, pending.Dependencies);
|
||||
|
||||
string? failureReason = null;
|
||||
@@ -604,7 +599,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
|
||||
/// <summary>Record a successful evaluation. MUST be called under <see cref="_lock"/>; returns what to
|
||||
/// publish, or null when the result is deduped.
|
||||
/// <para><b>The dedup key is (value, status), not value alone</b> — 05/STAB-19 generalising the
|
||||
/// <para><b>The dedup key is (value, status), not value alone</b> — generalising the
|
||||
/// Bad-recovery bypass 02/S13 introduced. Recovery is a publish, never an assumption: the node is
|
||||
/// currently carrying the previous status, so a result whose VALUE is unchanged but whose STATUS
|
||||
/// differs — the shape of every recovery, since a device that comes back usually comes back holding
|
||||
@@ -629,7 +624,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
return (value, statusCode);
|
||||
}
|
||||
|
||||
/// <summary>Record that this tag's INPUTS are Bad, so no evaluation ran (05/STAB-19). Publishes the
|
||||
/// <summary>Record that this tag's INPUTS are Bad, so no evaluation ran. Publishes the
|
||||
/// worst input's status — carrying the last known value — <b>once per change of that status</b>: a
|
||||
/// repeat of the same Bad is silent, while <c>BadNoCommunication</c> arriving over an earlier
|
||||
/// <c>BadInternalError</c> (or the reverse) is not masked, because the sub-code is what names which
|
||||
@@ -720,7 +715,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
// always carries a non-null handle.
|
||||
private static readonly CalculationSubscriptionHandle SharedHandle = new("calc-shared");
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Stops the timers and disposes the script evaluator.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
@@ -742,7 +737,7 @@ public sealed class CalculationDriver : IDriver, IDependencyConsumer, ISubscriba
|
||||
public bool HasPublished;
|
||||
|
||||
/// <summary>The status code last published for this tag. Replaces the old two-state
|
||||
/// <c>LastPublishedBad</c> flag (05/STAB-19): the dedup key is (value, status), and a Bad status
|
||||
/// <c>LastPublishedBad</c> flag: the dedup key is (value, status), and a Bad status
|
||||
/// now carries the failing INPUT's sub-code rather than a fixed <c>BadInternalError</c>.</summary>
|
||||
public uint LastPublishedStatus;
|
||||
public DateTime LastTimestampUtc;
|
||||
|
||||
Reference in New Issue
Block a user