docs(code): honest rationales — Akka restart semantics, per-key shards, EF literal inlining; retire or annotate orphaned members
This commit is contained in:
@@ -8,16 +8,20 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Historian;
|
||||
/// <summary>
|
||||
/// Continuous-historization engine for non-Galaxy (driver) tags. Registers interest with the
|
||||
/// per-node <see cref="DependencyMuxActor"/> for the configured historized tag refs, then taps the
|
||||
/// <see cref="VirtualTagActor.DependencyValueChanged"/> values the mux fans for those refs:
|
||||
/// values the mux fans for those refs — in production a
|
||||
/// <see cref="VirtualTagActor.DependencyValueBatch"/> per driver burst, with the per-value
|
||||
/// <see cref="VirtualTagActor.DependencyValueChanged"/> receive retained for direct senders and tests:
|
||||
/// value → coerce to numeric → append to the durable <see cref="IHistorizationOutbox"/> (the crash
|
||||
/// boundary) → a self-paced drain writes the outbox through <see cref="IHistorianValueWriter"/>'s
|
||||
/// live-value path and acks (truncates) on success.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <b>Message path (grounded against the real actors).</b> The mux fans
|
||||
/// <see cref="VirtualTagActor.DependencyValueChanged"/> — which carries only
|
||||
/// <c>(TagId, Value, TimestampUtc)</c> and <em>no quality</em> — to every registered subscriber.
|
||||
/// <b>Message path (grounded against the real actors).</b> The mux fans each value — carrying
|
||||
/// only <c>(TagId, Value, TimestampUtc)</c> and <em>no quality</em> — to every registered
|
||||
/// subscriber, batched as a <see cref="VirtualTagActor.DependencyValueBatch"/> on the production
|
||||
/// path and as a bare <see cref="VirtualTagActor.DependencyValueChanged"/> from a direct sender
|
||||
/// or a test.
|
||||
/// The recorder reuses that existing fan-out (no change to <c>DriverHostActor</c>), so values
|
||||
/// arrive Good-quality by the same convention the scripted-alarm host uses (the mux only
|
||||
/// forwards driver-published values); historized samples are recorded with
|
||||
|
||||
@@ -29,9 +29,11 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.ScriptedAlarms;
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// <b>Data flow.</b> <see cref="DependencyMuxActor"/> delivers a
|
||||
/// <see cref="VirtualTagActor.DependencyValueChanged"/> for every tag the loaded alarms
|
||||
/// depend on; the host pushes each into the upstream. The engine self-evaluates: its own
|
||||
/// <b>Data flow.</b> <see cref="DependencyMuxActor"/> delivers the values of every tag the
|
||||
/// loaded alarms depend on — in production as a batched
|
||||
/// <see cref="VirtualTagActor.DependencyValueBatch"/> per driver burst, with the per-value
|
||||
/// <see cref="VirtualTagActor.DependencyValueChanged"/> receive retained for direct senders and
|
||||
/// tests; the host pushes each into the upstream. The engine self-evaluates: its own
|
||||
/// <see cref="ITagUpstreamSource.SubscribeTag"/> observer re-runs the predicates and raises
|
||||
/// <see cref="ScriptedAlarmEngine.OnEvent"/>. The host does NOT call evaluate — it only
|
||||
/// feeds values in and fans emissions out.
|
||||
@@ -134,9 +136,10 @@ public sealed class ScriptedAlarmHostActor : ReceiveActor
|
||||
/// <summary>Factory method to create Props for a <see cref="ScriptedAlarmHostActor"/>.</summary>
|
||||
/// <param name="publishActor">The OPC UA publish actor that consumes
|
||||
/// <see cref="OpcUaPublishActor.AlarmStateUpdate"/> bridged from engine emissions.</param>
|
||||
/// <param name="mux">Optional dependency multiplexer the host registers interest with so it
|
||||
/// receives a <see cref="VirtualTagActor.DependencyValueChanged"/> per dependency tag. Null on the
|
||||
/// dev/Mac path (no live values).</param>
|
||||
/// <param name="mux">Optional dependency multiplexer the host registers interest with so it receives
|
||||
/// its dependency tags' values — a <see cref="VirtualTagActor.DependencyValueBatch"/> per burst in
|
||||
/// production, or a per-value <see cref="VirtualTagActor.DependencyValueChanged"/> from a direct
|
||||
/// sender or a test. Null on the dev/Mac path (no live values).</param>
|
||||
/// <param name="upstream">The mux-fed upstream the engine reads + subscribes from. MUST be the
|
||||
/// same instance the <paramref name="engine"/> was constructed around.</param>
|
||||
/// <param name="engine">The scripted-alarm engine this host owns + disposes.</param>
|
||||
@@ -403,10 +406,12 @@ public sealed class ScriptedAlarmHostActor : ReceiveActor
|
||||
/// Loops the per-value handler, preserving in-burst order.</summary>
|
||||
/// <remarks>
|
||||
/// <b>Mid-batch exception policy: unguarded, deliberately.</b> An exception escaping
|
||||
/// <see cref="OnDependencyChanged"/> drops the remaining items of this burst and restarts the actor
|
||||
/// — exactly what it already did when the same values arrived as N separate messages (the tail is
|
||||
/// then lost to the mailbox flush instead of to the loop), so batching changes the blast radius by
|
||||
/// nothing. Catching per item is deliberately NOT done: the handler is a single
|
||||
/// <see cref="OnDependencyChanged"/> drops the remaining items of this burst and restarts the actor.
|
||||
/// That IS wider than the per-message path — Akka restarts do not flush the mailbox, only the
|
||||
/// failing message is dropped, so as N separate messages the same fault would cost one value rather
|
||||
/// than the burst's tail. Accepted: the engine tolerates a missed intermediate value (the next
|
||||
/// delivery for that tag re-converges its state). Catching per item is deliberately NOT done: the
|
||||
/// handler is a single
|
||||
/// <c>IUpstreamValueSource.Push</c> into an in-memory cache, so a throw means the upstream itself is
|
||||
/// broken and swallowing it would feed the engine a silently truncated burst. Contrast
|
||||
/// <c>ContinuousHistorizationRecorder.IngestAsync</c>, which DOES catch per item because its
|
||||
|
||||
@@ -8,9 +8,11 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.VirtualTags;
|
||||
/// Bridges a driver that implements <see cref="IDependencyConsumer"/> onto the per-node
|
||||
/// <see cref="DependencyMuxActor"/>. Spawned as a child of <c>DriverHostActor</c> for each such
|
||||
/// driver: on start (and on every apply via <see cref="ReRegister"/>) it registers the driver's
|
||||
/// declared <see cref="IDependencyConsumer.DependencyRefs"/> with the mux, and forwards each
|
||||
/// <see cref="VirtualTagActor.DependencyValueChanged"/> the mux fans out into
|
||||
/// <see cref="IDependencyConsumer.OnDependencyValue"/>.
|
||||
/// declared <see cref="IDependencyConsumer.DependencyRefs"/> with the mux, and forwards each value
|
||||
/// the mux fans out into <see cref="IDependencyConsumer.OnDependencyValue"/>. The production
|
||||
/// delivery is the batched <see cref="VirtualTagActor.DependencyValueBatch"/> — one message per
|
||||
/// driver burst; the per-value <see cref="VirtualTagActor.DependencyValueChanged"/> receive remains
|
||||
/// for direct senders and tests, and the batch handler simply loops it.
|
||||
///
|
||||
/// <para>
|
||||
/// This is the exact seam a <c>VirtualTagActor</c> uses to receive its inputs, generalised so a
|
||||
@@ -76,11 +78,13 @@ public sealed class DependencyConsumerMuxAdapter : ReceiveActor
|
||||
/// <remarks>
|
||||
/// <b>Mid-batch exception policy: unguarded, matching the single-value path.</b> An exception
|
||||
/// escaping <see cref="IDependencyConsumer.OnDependencyValue"/> drops the remaining items of this
|
||||
/// burst and restarts the adapter — the same outcome the single-value handler already has (there the
|
||||
/// tail is lost to the mailbox flush rather than to the loop), so batching does not widen it.
|
||||
/// Catching per item HERE only would make the batch path quietly more forgiving than the single-value
|
||||
/// one for the same consumer fault, so the two are deliberately kept identical: a consumer that needs
|
||||
/// per-value fault tolerance owns it inside its own <c>OnDependencyValue</c>.
|
||||
/// burst and restarts the adapter. This DOES widen the per-fault loss: Akka restarts do not flush
|
||||
/// the mailbox (only the failing message is dropped), so as N separate messages the same fault
|
||||
/// would have cost one value, while batched it costs the rest of the burst's tail. Accepted,
|
||||
/// because an <see cref="IDependencyConsumer"/> tolerates missed intermediate values — the next
|
||||
/// delivery re-converges its state — and catching per item HERE only would make the batch path
|
||||
/// quietly more forgiving than the single-value one for the same consumer fault. A consumer that
|
||||
/// needs per-value fault tolerance owns it inside its own <c>OnDependencyValue</c>.
|
||||
/// </remarks>
|
||||
/// <param name="msg">The batch of matched dependency values.</param>
|
||||
private void OnDependencyValueBatch(VirtualTagActor.DependencyValueBatch msg)
|
||||
|
||||
Reference in New Issue
Block a user