docs(comments): strip internal task/milestone/bundle bookkeeping from code comments
Remove project bookkeeping citations from shipped code comments across the solution: hyphenated task IDs (WP-14, StoreAndForward-025), milestone/task/ issue refs (M3, Task 4, Audit Log #23, #21), Bundle X task-bundle labels, and C/D/K/S/T phase labels. Comment text only — no code logic, string/log literals, or XML-doc structure changed. Genuine descriptions are preserved (only the citation is stripped), and technical lookalikes are retained (UTF-8, SHA-256, T00:00:00, M365, UTC-5, pre-C4/pre-C5 schema versions). Flagged by the new CommentChecker TaskReferenceInComment / TrackingReferenceInComment checks plus targeted grep passes; full solution builds clean, append-only guard tests pass.
This commit is contained in:
@@ -25,13 +25,13 @@ namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Actors;
|
||||
/// (loaded from FlattenedConfiguration + static overrides from SQLite).
|
||||
///
|
||||
/// The Instance Actor is the single source of truth for runtime instance state.
|
||||
/// WP-24: All state mutations are serialized through the actor mailbox.
|
||||
/// All state mutations are serialized through the actor mailbox.
|
||||
/// Multiple Script Execution Actors run concurrently; state mutations through this actor.
|
||||
///
|
||||
/// WP-15/16: Creates child Script Actors and Alarm Actors on startup.
|
||||
/// WP-22: Tell for tag value updates, attribute notifications, stream publishing.
|
||||
/// Creates child Script Actors and Alarm Actors on startup.
|
||||
/// Tell for tag value updates, attribute notifications, stream publishing.
|
||||
/// Ask for CallScript, debug snapshot.
|
||||
/// WP-25: Debug view backend — snapshot + stream subscription.
|
||||
/// Debug view backend — snapshot + stream subscription.
|
||||
/// </summary>
|
||||
public class InstanceActor : ReceiveActor
|
||||
{
|
||||
@@ -68,7 +68,7 @@ public class InstanceActor : ReceiveActor
|
||||
private readonly Dictionary<string, AlarmStateChanged> _latestAlarmEvents = new();
|
||||
private FlattenedConfiguration? _configuration;
|
||||
|
||||
// MV-8: resolved attributes indexed by canonical name. The TagValueUpdate
|
||||
// Resolved attributes indexed by canonical name. The TagValueUpdate
|
||||
// ingest path is the highest-frequency message this actor handles, so the
|
||||
// attribute lookup must be O(1) rather than a linear scan of
|
||||
// _configuration.Attributes. Built once in the constructor from the
|
||||
@@ -144,11 +144,11 @@ public class InstanceActor : ReceiveActor
|
||||
{
|
||||
foreach (var attr in _configuration.Attributes)
|
||||
{
|
||||
// MV-8: index resolved attributes for O(1) lookup on the hot
|
||||
// Index resolved attributes for O(1) lookup on the hot
|
||||
// TagValueUpdate ingest path (last-wins on duplicate names).
|
||||
_resolvedAttributeByName[attr.CanonicalName] = attr;
|
||||
|
||||
// MV-7: a STATIC List attribute's default is the canonical JSON
|
||||
// A STATIC List attribute's default is the canonical JSON
|
||||
// array string. Decode it to a typed List<T> for in-memory reads
|
||||
// so scripts see a real collection. Scalars store their raw
|
||||
// string unchanged. A malformed List default decodes to null and
|
||||
@@ -176,7 +176,7 @@ public class InstanceActor : ReceiveActor
|
||||
// Handle static attribute writes
|
||||
Receive<SetStaticAttributeCommand>(HandleSetStaticAttribute);
|
||||
|
||||
// SiteRuntime-019: the disable/enable lifecycle is owned entirely by the
|
||||
// The disable/enable lifecycle is owned entirely by the
|
||||
// Deployment Manager — DeploymentManagerActor.HandleDisable/HandleEnable
|
||||
// stop or re-create the Instance Actor directly and reply to the caller.
|
||||
// DisableInstanceCommand / EnableInstanceCommand are never routed to the
|
||||
@@ -184,10 +184,10 @@ public class InstanceActor : ReceiveActor
|
||||
// handlers were dead code that implied a non-existent instance-side
|
||||
// acknowledgement contract.)
|
||||
|
||||
// WP-15: Handle script call requests — route to appropriate Script Actor (Ask pattern)
|
||||
// Handle script call requests — route to appropriate Script Actor (Ask pattern)
|
||||
Receive<ScriptCallRequest>(HandleScriptCallRequest);
|
||||
|
||||
// WP-22/23: Handle attribute value changes from DCL (Tell pattern)
|
||||
// Handle attribute value changes from DCL (Tell pattern)
|
||||
Receive<AttributeValueChanged>(HandleAttributeValueChanged);
|
||||
|
||||
// WaitForAttribute (spec §4.2): event-driven "wait for value" waiter
|
||||
@@ -207,16 +207,16 @@ public class InstanceActor : ReceiveActor
|
||||
Receive<SubscribeTagsResponse>(_ => { }); // Ack from DCL subscribe — no action needed
|
||||
Receive<ConnectionQualityChanged>(HandleConnectionQualityChanged);
|
||||
|
||||
// WP-16: Handle alarm state changes from Alarm Actors (Tell pattern)
|
||||
// Handle alarm state changes from Alarm Actors (Tell pattern)
|
||||
Receive<AlarmStateChanged>(HandleAlarmStateChanged);
|
||||
|
||||
// SiteRuntime-027: a NativeAlarmActor tells us when one of its native
|
||||
// A NativeAlarmActor tells us when one of its native
|
||||
// conditions has left the mirror for good (snapshot-swap removal, retention
|
||||
// drop, or cap eviction) so we can evict the stale _latestAlarmEvents key
|
||||
// and not leak per-instance memory / bloat DebugView snapshots.
|
||||
Receive<NativeAlarmDropped>(HandleNativeAlarmDropped);
|
||||
|
||||
// WP-25: Debug view subscribe/unsubscribe (Ask pattern for snapshot)
|
||||
// Debug view subscribe/unsubscribe (Ask pattern for snapshot)
|
||||
Receive<SubscribeDebugViewRequest>(HandleSubscribeDebugView);
|
||||
Receive<UnsubscribeDebugViewRequest>(HandleUnsubscribeDebugView);
|
||||
|
||||
@@ -233,7 +233,7 @@ public class InstanceActor : ReceiveActor
|
||||
base.PreStart();
|
||||
_logger.LogInformation("InstanceActor started for {Instance}", _instanceUniqueName);
|
||||
|
||||
// M1.6: operational `instance_lifecycle` event — instance started.
|
||||
// Operational `instance_lifecycle` event — instance started.
|
||||
// An instance starts on deploy, on enable (DeploymentManager re-creates
|
||||
// the actor), and on failover/restart; this single point covers them all.
|
||||
LogLifecycleEvent($"Instance {_instanceUniqueName} started");
|
||||
@@ -257,7 +257,7 @@ public class InstanceActor : ReceiveActor
|
||||
/// <inheritdoc />
|
||||
protected override void PostStop()
|
||||
{
|
||||
// M1.6: operational `instance_lifecycle` event — instance stopped. An
|
||||
// Operational `instance_lifecycle` event — instance stopped. An
|
||||
// instance stops on disable, delete, redeployment, and graceful shutdown;
|
||||
// this single point covers them all.
|
||||
LogLifecycleEvent($"Instance {_instanceUniqueName} stopped");
|
||||
@@ -265,7 +265,7 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// M1.6: fire-and-forget an <c>instance_lifecycle</c> operational event to the
|
||||
/// Fire-and-forget an <c>instance_lifecycle</c> operational event to the
|
||||
/// optional <see cref="ISiteEventLogger"/>. Resolved optionally and never
|
||||
/// awaited so a logging failure cannot affect the instance lifecycle
|
||||
/// (matching the established ScriptActor/ScriptExecutionActor pattern).
|
||||
@@ -311,7 +311,7 @@ public class InstanceActor : ReceiveActor
|
||||
|
||||
/// <summary>
|
||||
/// Handles an attribute write (<c>Instance.SetAttribute</c> / Inbound API).
|
||||
/// WP-24: State mutation serialized through this actor's mailbox.
|
||||
/// State mutation serialized through this actor's mailbox.
|
||||
///
|
||||
/// The write is routed by the attribute's data binding:
|
||||
/// * Data-sourced attribute → forwards a <see cref="WriteTagRequest"/> to the
|
||||
@@ -330,7 +330,7 @@ public class InstanceActor : ReceiveActor
|
||||
var resolved = _configuration?.Attributes
|
||||
.FirstOrDefault(a => a.CanonicalName == command.AttributeName);
|
||||
|
||||
// SiteRuntime-025: reject writes targeting an attribute that does not exist
|
||||
// Reject writes targeting an attribute that does not exist
|
||||
// on the deployed instance. Without this check, an inbound API
|
||||
// SetAttribute("notARealAttr", ...) would pollute the in-memory
|
||||
// _attributes dictionary, publish a synthetic AttributeValueChanged to
|
||||
@@ -373,7 +373,7 @@ public class InstanceActor : ReceiveActor
|
||||
/// </summary>
|
||||
private void HandleSetStaticAttributeCore(SetStaticAttributeCommand command)
|
||||
{
|
||||
// MV-7: command.Value is the canonical form — a plain string for scalars,
|
||||
// command.Value is the canonical form — a plain string for scalars,
|
||||
// a JSON array string for List attributes. For a List attribute we store
|
||||
// the DECODED typed list in memory (so scripts read a real collection) but
|
||||
// persist + publish the canonical JSON string UNCHANGED below. Scalars
|
||||
@@ -382,7 +382,7 @@ public class InstanceActor : ReceiveActor
|
||||
if (_resolvedAttributeByName.TryGetValue(command.AttributeName, out var resolved)
|
||||
&& IsListAttribute(resolved))
|
||||
{
|
||||
// MV-7: the script path pre-encodes valid canonical JSON via ScopeAccessors,
|
||||
// The script path pre-encodes valid canonical JSON via ScopeAccessors,
|
||||
// but the Inbound API / direct-command path can submit an arbitrary
|
||||
// command.Value. A non-empty value that fails to decode (malformed JSON,
|
||||
// bad element, missing element type) is poison: storing it would null the
|
||||
@@ -415,7 +415,7 @@ public class InstanceActor : ReceiveActor
|
||||
_attributes[command.AttributeName] = command.Value;
|
||||
}
|
||||
|
||||
// Publish attribute change to stream (WP-23) and notify children
|
||||
// Publish attribute change to stream and notify children
|
||||
var changed = new AttributeValueChanged(
|
||||
_instanceUniqueName,
|
||||
command.AttributeName,
|
||||
@@ -469,7 +469,7 @@ public class InstanceActor : ReceiveActor
|
||||
return;
|
||||
}
|
||||
|
||||
// MV (C1): for a data-sourced List attribute the incoming command.Value is
|
||||
// MV: for a data-sourced List attribute the incoming command.Value is
|
||||
// the canonical JSON array string (ScopeAccessors encodes the script's
|
||||
// List<T> for transport/storage). Writing that string straight to the DCL
|
||||
// would push a String scalar to an array node. Decode it back to a typed
|
||||
@@ -632,8 +632,8 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WP-15: Routes script call requests to the appropriate Script Actor.
|
||||
/// Uses Ask pattern (WP-22).
|
||||
/// Routes script call requests to the appropriate Script Actor.
|
||||
/// Uses Ask pattern.
|
||||
/// </summary>
|
||||
private void HandleScriptCallRequest(ScriptCallRequest request)
|
||||
{
|
||||
@@ -641,7 +641,7 @@ public class InstanceActor : ReceiveActor
|
||||
{
|
||||
// Forward the request to the Script Actor, preserving the original
|
||||
// sender. The whole record is forwarded unchanged, so any
|
||||
// ParentExecutionId (Audit Log #23) set by an inbound-API-routed
|
||||
// ParentExecutionId set by an inbound-API-routed
|
||||
// call is carried through to the Script Actor verbatim.
|
||||
scriptActor.Forward(request);
|
||||
}
|
||||
@@ -656,12 +656,12 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WP-22/23: Handles attribute value changes from DCL or static writes.
|
||||
/// Handles attribute value changes from DCL or static writes.
|
||||
/// Updates in-memory state, publishes to stream, and notifies children.
|
||||
/// </summary>
|
||||
private void HandleAttributeValueChanged(AttributeValueChanged changed)
|
||||
{
|
||||
// WP-24: State mutation serialized through this actor
|
||||
// State mutation serialized through this actor
|
||||
_attributes[changed.AttributeName] = changed.Value;
|
||||
_attributeQualities[changed.AttributeName] = changed.Quality;
|
||||
_attributeTimestamps[changed.AttributeName] = changed.Timestamp;
|
||||
@@ -791,10 +791,10 @@ public class InstanceActor : ReceiveActor
|
||||
// we resolve and convert per attribute rather than once for the tag.
|
||||
foreach (var attrName in attrNames)
|
||||
{
|
||||
// MV-8: O(1) lookup off the hot ingest path (was a linear FirstOrDefault).
|
||||
// O(1) lookup off the hot ingest path (was a linear FirstOrDefault).
|
||||
_resolvedAttributeByName.TryGetValue(attrName, out var resolved);
|
||||
|
||||
// MV-8: a List-typed attribute coerces the incoming OPC UA array
|
||||
// A List-typed attribute coerces the incoming OPC UA array
|
||||
// (a CLR array/IEnumerable from the SDK) into a typed List<T>. On an
|
||||
// element-type mismatch we set the attribute's quality to Bad, log a
|
||||
// warning, and skip storing a value rather than crashing the actor.
|
||||
@@ -845,12 +845,12 @@ public class InstanceActor : ReceiveActor
|
||||
&& dt == DataType.List;
|
||||
|
||||
/// <summary>
|
||||
/// MV-7: decodes a STATIC (authored / overridden) attribute's canonical value
|
||||
/// Decodes a STATIC (authored / overridden) attribute's canonical value
|
||||
/// for in-memory storage. List attributes carry a canonical JSON array string
|
||||
/// (config default or persisted override) which is decoded via
|
||||
/// <see cref="AttributeValueCodec.Decode"/> into a typed <c>List<T></c>
|
||||
/// so scripts read a real collection; scalars pass through unchanged. This is
|
||||
/// the authored counterpart to MV-8's <see cref="TryCoerceListValue"/> (which
|
||||
/// the authored counterpart to <see cref="TryCoerceListValue"/> (which
|
||||
/// coerces live OPC UA CLR arrays). An undecodable List value (malformed JSON,
|
||||
/// bad element, missing element type) degrades to <see langword="null"/> + a
|
||||
/// warning — the caller marks the attribute Bad quality. NEVER throws into the
|
||||
@@ -879,7 +879,7 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MV-8: coerces an incoming data-sourced value (an OPC UA array / IEnumerable)
|
||||
/// Coerces an incoming data-sourced value (an OPC UA array / IEnumerable)
|
||||
/// into a typed <c>List<elementClrType></c> matching the attribute's
|
||||
/// <see cref="ResolvedAttribute.ElementDataType"/>. Each element is converted
|
||||
/// with invariant culture (round-trip parse for DateTime). Returns
|
||||
@@ -1008,7 +1008,7 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WP-16: Handles alarm state changes from Alarm Actors.
|
||||
/// Handles alarm state changes from Alarm Actors.
|
||||
/// Updates in-memory alarm state and publishes to stream.
|
||||
/// </summary>
|
||||
private void HandleAlarmStateChanged(AlarmStateChanged changed)
|
||||
@@ -1019,12 +1019,12 @@ public class InstanceActor : ReceiveActor
|
||||
// DebugView snapshot reflects it — native alarms have no _alarmActors entry.
|
||||
_latestAlarmEvents[changed.AlarmName] = changed;
|
||||
|
||||
// WP-23: Publish to site-wide stream
|
||||
// Publish to site-wide stream
|
||||
_streamManager?.PublishAlarmStateChanged(changed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SiteRuntime-027: evicts a native condition's key from the alarm-state maps once
|
||||
/// Evicts a native condition's key from the alarm-state maps once
|
||||
/// the owning <see cref="NativeAlarmActor"/> has dropped it from its mirror (after
|
||||
/// emitting the condition's final return-to-normal). Without this the
|
||||
/// <c>_latestAlarmEvents</c> map grows without bound on a source that mints a fresh
|
||||
@@ -1043,7 +1043,7 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WP-25: Debug view subscribe — returns snapshot and begins streaming.
|
||||
/// Debug view subscribe — returns snapshot and begins streaming.
|
||||
/// </summary>
|
||||
private void HandleSubscribeDebugView(SubscribeDebugViewRequest request)
|
||||
{
|
||||
@@ -1123,7 +1123,7 @@ public class InstanceActor : ReceiveActor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WP-25: Debug view unsubscribe (SiteRuntime-013).
|
||||
/// Debug view unsubscribe.
|
||||
/// This handler is a deliberate no-op acknowledgement: the Instance Actor holds
|
||||
/// no per-subscriber state. The real debug-stream subscription lifecycle lives in
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.SiteRuntime.Streaming.SiteStreamManager"/>
|
||||
@@ -1164,7 +1164,7 @@ public class InstanceActor : ReceiveActor
|
||||
|
||||
/// <summary>
|
||||
/// Publishes attribute change to stream and notifies child Script/Alarm actors.
|
||||
/// WP-22: Tell for attribute notifications (fire-and-forget, never blocks).
|
||||
/// Tell for attribute notifications (fire-and-forget, never blocks).
|
||||
/// </summary>
|
||||
/// <param name="changed">The attribute change to publish.</param>
|
||||
/// <param name="evaluateWaiters">
|
||||
@@ -1178,7 +1178,7 @@ public class InstanceActor : ReceiveActor
|
||||
/// </param>
|
||||
private void PublishAndNotifyChildren(AttributeValueChanged changed, bool evaluateWaiters = true)
|
||||
{
|
||||
// WP-23: Publish to site-wide stream
|
||||
// Publish to site-wide stream
|
||||
_streamManager?.PublishAttributeValueChanged(changed);
|
||||
|
||||
// Notify Script Actors (for value-change and conditional triggers)
|
||||
@@ -1286,14 +1286,14 @@ public class InstanceActor : ReceiveActor
|
||||
|
||||
foreach (var kvp in result.Overrides)
|
||||
{
|
||||
// MV-7: persisted override values are canonical strings — a JSON array
|
||||
// Persisted override values are canonical strings — a JSON array
|
||||
// string for List attributes, a plain string for scalars. Decode List
|
||||
// overrides to a typed list (matching the config-default load), set
|
||||
// Bad quality on a malformed stored value, and never crash the actor.
|
||||
if (_resolvedAttributeByName.TryGetValue(kvp.Key, out var resolved)
|
||||
&& IsListAttribute(resolved))
|
||||
{
|
||||
// NJ-4: decode the stored List override (both old array-of-strings
|
||||
// Decode the stored List override (both old array-of-strings
|
||||
// and native-typed forms decode) and re-persist the native form if
|
||||
// the stored value is still in the OLD form. Re-encoding the decoded
|
||||
// list and comparing to the stored string detects old-form values
|
||||
@@ -1334,11 +1334,11 @@ public class InstanceActor : ReceiveActor
|
||||
|
||||
/// <summary>
|
||||
/// Creates child Script Actors and Alarm Actors from the flattened configuration.
|
||||
/// WP-15: Script Actors spawned per script definition.
|
||||
/// WP-16: Alarm Actors spawned per alarm definition, as peers to Script Actors.
|
||||
/// WP-32: Compilation errors reject entire instance deployment (logged but actor still starts).
|
||||
/// Script Actors spawned per script definition.
|
||||
/// Alarm Actors spawned per alarm definition, as peers to Script Actors.
|
||||
/// Compilation errors reject entire instance deployment (logged but actor still starts).
|
||||
///
|
||||
/// SiteRuntime-017: each child is seeded from a private point-in-time snapshot
|
||||
/// Each child is seeded from a private point-in-time snapshot
|
||||
/// of <c>_attributes</c>, NOT the live dictionary. The snapshot is taken here on
|
||||
/// the Instance Actor thread, so it is race-free; handing the live mutable
|
||||
/// <see cref="System.Collections.Generic.Dictionary{TKey,TValue}"/> by reference
|
||||
@@ -1349,7 +1349,7 @@ public class InstanceActor : ReceiveActor
|
||||
{
|
||||
if (_configuration == null) return;
|
||||
|
||||
// SiteRuntime-017: snapshot the live attribute dictionary once, on the
|
||||
// Snapshot the live attribute dictionary once, on the
|
||||
// Instance Actor thread, before any child is constructed. Each child
|
||||
// Props closure captures this immutable copy instead of the mutable
|
||||
// _attributes field, so no child constructor ever enumerates a
|
||||
@@ -1395,7 +1395,7 @@ public class InstanceActor : ReceiveActor
|
||||
foreach (var alarm in _configuration.Alarms)
|
||||
{
|
||||
Script<object?>? onTriggerScript = null;
|
||||
// M2.5 (#9): the on-trigger script's per-script execution timeout,
|
||||
// The on-trigger script's per-script execution timeout,
|
||||
// captured from its ResolvedScript so the AlarmExecutionActor can
|
||||
// apply perScript ?? global. Null when there is no on-trigger script.
|
||||
int? onTriggerTimeoutSeconds = null;
|
||||
@@ -1441,7 +1441,7 @@ public class InstanceActor : ReceiveActor
|
||||
attributeSnapshot,
|
||||
_healthCollector,
|
||||
_serviceProvider,
|
||||
// M2.5 (#9): per-script timeout for the alarm on-trigger script.
|
||||
// Per-script timeout for the alarm on-trigger script.
|
||||
onTriggerTimeoutSeconds));
|
||||
|
||||
var actorRef = Context.ActorOf(props, $"alarm-{alarm.CanonicalName}");
|
||||
|
||||
Reference in New Issue
Block a user