docs(code): correct comments stale after the perf remainder

This commit is contained in:
Joseph Doherty
2026-08-16 05:09:00 -04:00
parent e75bb38734
commit dbc9223206
6 changed files with 17 additions and 15 deletions
@@ -101,10 +101,10 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
/// state — a no-op when already Reconnecting or Connecting.
/// </summary>
public sealed record ForceReconnect;
/// <summary>One driver-published value. NOT sent to the parent by the subscription path any more — the
/// actor batches every data change into an <see cref="AttributeValueBatchPublished"/>. Still live as the
/// per-value message the parent fans onward (the dependency mux consumes it, and
/// <c>DriverHostActor.FanCommsLossToDependencyMux</c> fabricates it).
/// <summary>One driver-published value. <b>No production sender remains</b> — the subscription path
/// batches every data change into an <see cref="AttributeValueBatchPublished"/>, and the comms-loss fan
/// (<c>DriverHostActor.FanCommsLossToDependencyMux</c>), which was the last sender to fabricate this
/// message, now fabricates a batch too. The dependency mux still accepts it for tests and direct senders.
/// <para><paramref name="StatusCode"/> is the driver's full OPC UA status code including its sub-code
/// (#519) — not a severity bucket. Classify it with <see cref="OpcUaStatus.IsGood"/> and friends rather
/// than comparing it to <see cref="OpcUaStatus.Good"/>.</para></summary>
@@ -402,7 +402,7 @@ public static class ServiceCollectionExtensions
}
// Dependency mux must be spawned before DriverHostActor so the host can forward
// AttributeValuePublished into it from the very first driver spawn.
// AttributeValueBatchPublished into it from the very first driver spawn.
var mux = system.ActorOf(DependencyMuxActor.Props(), DependencyMuxActorName);
registry.Register<DependencyMuxActorKey>(mux);
@@ -5,7 +5,7 @@ using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
namespace ZB.MOM.WW.OtOpcUa.Runtime.VirtualTags;
/// <summary>
/// Per-node fan-out router from <see cref="DriverInstanceActor.AttributeValuePublished"/>
/// Per-node fan-out router from <see cref="DriverInstanceActor.AttributeValueBatchPublished"/>
/// to interested <see cref="VirtualTagActor"/> instances. VirtualTagActor sends
/// <see cref="RegisterInterest"/> on start-up listing the tag refs it depends on; the mux
/// keeps a map of <c>tagRef → Set&lt;IActorRef&gt;</c> and on every ingress forwards each
@@ -16,11 +16,12 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.VirtualTags;
/// node). The ONLY driver ingress is the batched
/// <see cref="DriverInstanceActor.AttributeValueBatchPublished"/> — one envelope per driver
/// production burst, which the mux filters per item. The per-value
/// <see cref="DriverInstanceActor.AttributeValuePublished"/> receive stays for the comms-loss fan
/// ALONE: <c>DriverHostActor.FanCommsLossToDependencyMux</c> fabricates that message and Tells this
/// mux directly, never through the host's own receive.
/// <see cref="DriverInstanceActor.AttributeValuePublished"/> receive has <b>no production sender left
/// at all</b>: the comms-loss fan (<c>DriverHostActor.FanCommsLossToDependencyMux</c>) was its last
/// one and now fabricates an <c>AttributeValueBatchPublished</c> instead. The receive is kept for
/// tests and direct senders — treat it as dead in production.
///
/// <b>The mux emits ONLY batches</b> (the comms-loss fan as a single-item one), so a subscriber's
/// <b>The mux emits ONLY batches</b>, so a subscriber's
/// batch receive is its complete hot path. Every subscriber keeps a per-value
/// <see cref="VirtualTagActor.DependencyValueChanged"/> receive as well, for direct senders and tests.
/// The mux is deliberately not a DPS subscriber — virtual-tag evaluation is local to each node and
@@ -115,8 +116,8 @@ public sealed class DependencyMuxActor : ReceiveActor
{
// A single-item batch, so the mux emits exactly ONE message shape and every subscriber needs
// only the batch receive on its hot path. One list per subscriber: batch ownership transfers
// to the receiver, so a shared list must never cross mailboxes. This is the comms-loss fan
// (one ref, on a driver disconnect), not the steady value path — the extra allocation is noise.
// to the receiver, so a shared list must never cross mailboxes. Nothing in production reaches
// this path (see the class doc) — the extra allocation is noise on a test-only seam.
sub.Tell(new VirtualTagActor.DependencyValueBatch(new[] { dep }));
}
}
@@ -143,7 +143,7 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
public void AThrowingCache_DoesNotFailTheApply()
{
// By the time the cache runs, an Applied ACK has already gone to the coordinator. If a cache
// failure escaped, ApplyAndAck's catch would send a SECOND, contradictory Failed ACK for a
// failure escaped, HandleArtifactForApply's catch would send a SECOND, contradictory Failed ACK for a
// deployment the fleet already believes is live.
var db = NewInMemoryDbFactory();
var (deploymentId, _) = SeedDeployment(db, RevA, clusterId: null);
@@ -23,7 +23,7 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
/// </summary>
/// <remarks>
/// <para>
/// The ACK was never the thing at risk: <c>ApplyAndAck</c> sends it BEFORE it caches, so a
/// The ACK was never the thing at risk: <c>HandleArtifactForApply</c> sends it BEFORE it caches, so a
/// blocking store still acked promptly. What it blocked was <b>everything after</b> — the host
/// could not dequeue a driver value burst, a diagnostics request or the next dispatch until
/// SQLite was done. So the load-bearing assertion here is that the actor answers an unrelated
@@ -31,7 +31,8 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
/// Drives a real apply through <see cref="V3ArtifactSeeder"/>: the seeded artifact carries the v3
/// raw-tag chain (RawFolder → DriverInstance(RawFolderId) → Device → Tag) + an optional
/// UnsTagReference projecting each raw tag into an equipment. <c>DispatchDeployment</c> triggers the
/// <c>ApplyAndAck → PushDesiredSubscriptions</c> pass that builds the map; the sink and mux are
/// <c>BeginDirectApply → HandleArtifactForApply → PushDesiredSubscriptionsFromParsed</c> pass that
/// builds the map; the sink and mux are
/// injected as <see cref="Akka.TestKit.TestProbe"/>s.
/// </para>
/// </summary>