Resolve all 46 low-severity architecture review findings

This commit is contained in:
Joseph Doherty
2026-09-09 22:56:36 -04:00
parent fef3e7675f
commit 9ee402bbcd
139 changed files with 2621 additions and 1082 deletions
@@ -174,7 +174,7 @@ public class InstanceActor : ReceiveActor
/// <c>Trace</c>, and the arm is consumed. Bounded by the attribute count (one entry per
/// attribute, newest wins); no sweep — an unconsumed arm is overwritten or expires in place.
/// Armed at ISSUE, disarmed on a failed/timed-out write (arch-review F6, <see cref="DisarmTrace"/>);
/// a successful write's echo consumes it.
/// the first subsequent device update consumes it, with explicitly inferred linkage.
/// </summary>
private readonly Dictionary<string, (Guid SourceExecutionId, DateTimeOffset ExpiresAt)> _traceArms = new();
// Maps each tag path to every attribute canonical name that references it.
@@ -337,7 +337,7 @@ public class InstanceActor : ReceiveActor
Receive<RetryTagSubscribe>(msg => SendTagSubscribe(msg.ConnectionName));
// Arch-review F6: a traced write the DCL rejected (or that timed out) drops its own arm,
// so an unrelated later update is not stamped as that write's device echo.
// so a later update is not associated with that failed write.
Receive<DisarmTrace>(msg =>
{
if (_traceArms.TryGetValue(msg.AttributeName, out var arm)
@@ -751,10 +751,10 @@ public class InstanceActor : ReceiveActor
DateTimeOffset.UtcNow);
// Flow Debugger trace arm (design §5.3): only a TRACED write with a known writer arms;
// the device echo that follows is stamped in HandleTagValueUpdate. Untraced writes
// the next device update is marked as inferred in HandleTagValueUpdate. Untraced writes
// never touch the map, so production behaviour is unchanged. The arm is taken at ISSUE
// and dropped again on a failed/timed-out write (arch-review F6, via the DisarmTrace
// self-message below); a successful write's echo consumes it.
// self-message below); the first subsequent device update consumes it, with explicitly inferred linkage.
Guid? armed = null;
if (command.Trace && command.SourceExecutionId is { } traceSource)
{
@@ -1063,9 +1063,9 @@ public class InstanceActor : ReceiveActor
// O(1) lookup off the hot ingest path (was a linear FirstOrDefault).
_resolvedAttributeByName.TryGetValue(attrName, out var resolved);
// Flow Debugger trace arm (design §5.3): consume the arm for this attribute — the
// echo is stamped whatever its value (a device that clamps or rejects the write
// still shows what it did) — unless the arm has already expired.
// A device subscription has no write-request identity. Associate only the first
// update inside the arm window, explicitly as inferred: a periodic publish may
// win this race, and equality cannot establish causality (devices can coerce values).
Guid? traceSource = null;
var traced = false;
if (_traceArms.Remove(attrName, out var arm) && arm.ExpiresAt > DateTimeOffset.UtcNow)
@@ -1085,7 +1085,7 @@ public class InstanceActor : ReceiveActor
HandleAttributeValueChanged(new AttributeValueChanged(
_instanceUniqueName, update.TagPath, attrName,
typedList, QualityToString(update.Quality), update.Timestamp,
SourceExecutionId: traceSource, Trace: traced));
SourceExecutionId: traceSource, Trace: traced, SourceExecutionInferred: traced));
}
else
{
@@ -1103,7 +1103,7 @@ public class InstanceActor : ReceiveActor
PublishAndNotifyChildren(new AttributeValueChanged(
_instanceUniqueName, update.TagPath, attrName,
currentValue, "Bad", update.Timestamp,
SourceExecutionId: traceSource, Trace: traced), evaluateWaiters: false);
SourceExecutionId: traceSource, Trace: traced, SourceExecutionInferred: traced), evaluateWaiters: false);
}
continue;
}
@@ -1118,7 +1118,7 @@ public class InstanceActor : ReceiveActor
HandleAttributeValueChanged(new AttributeValueChanged(
_instanceUniqueName, update.TagPath, attrName,
value, QualityToString(update.Quality), update.Timestamp,
SourceExecutionId: traceSource, Trace: traced));
SourceExecutionId: traceSource, Trace: traced, SourceExecutionInferred: traced));
}
}