fix(review): remediate re-review findings — DCL-029/InboundAPI-031/SiteRuntime-032/StoreAndForward-028 + Low doc/test
Fixes the 8 findings from the 2026-06-24 re-review (commit c42bb485), with a
regression test per Medium finding:
- DataConnectionLayer-029 (Med): HandleAlarmSubscribeCompleted now mirrors the
tag-path re-check — if a feed is already stored for the source, release the
redundant just-created subscription instead of overwriting + leaking the first
one (the double-subscribe window DCL-023 reopened). +regression test.
- InboundAPI-031 (Med): remove WaitForAttribute's local 5s grace backstop (tighter
than the CommunicationService Ask's timeout+IntegrationTimeout round-trip budget,
so a slow-but-valid timed-out 'false' got cancelled into a 500). Link only the
client-abort + explicit caller tokens; the lower layer owns the backstop. +test.
- SiteRuntime-032 (Med): derive the deployed count from an authoritative set of
deployed config names (HashSet) instead of a map-presence-gated int, so deleting
a DISABLED instance decrements correctly (SiteRuntime-029's gate leaked it).
+deploy->disable->delete regression test.
- StoreAndForward-028 (Med): reset _bufferedCount in StopAsync alongside the
register-guard so a same-instance Stop->Start re-seeds from a clean base (no ~2N
gauge double-count). +restart regression test.
- AuditLog-017 (Low): test the OnIngestAsync scope-resolution guard (actor survives,
replies empty, counts the failure) — no longer unpinned.
- CentralUI-037 / ScriptAnalysis-009 / SiteRuntime-033 (Low): doc-comment + spec
fixes (Database-throws in the inbound sandbox; baseReferences param wording;
native-alarm cap return-to-normal + per-condition NativeAlarmDropped eviction).
Targeted suites green: SiteRuntime 5, StoreAndForward 6, InboundAPI 31,
DataConnectionLayer 10, AuditLog 5, ScriptAnalysis 40, CentralUI ScriptAnalysis 52.
This commit is contained in:
@@ -1822,8 +1822,29 @@ public class DataConnectionActor : UntypedActor, IWithStash, IWithTimers
|
||||
|
||||
if (msg.Success && msg.SubscriptionId != null)
|
||||
{
|
||||
_alarmSubscriptionIds[msg.SourceReference] = msg.SubscriptionId;
|
||||
_log.Info("[{0}] Alarm feed subscribed for source {1}", _connectionName, msg.SourceReference);
|
||||
// DataConnectionLayer-029: a concurrent unsubscribe clears the in-flight
|
||||
// marker (DCL-023), so a fresh subscribe for the same source can issue a
|
||||
// SECOND adapter feed before this completion fires — yielding two completions
|
||||
// for one source. Mirror the tag-path re-check (see HandleTagSubscribeCompleted,
|
||||
// the `_subscriptionIds.ContainsKey` guard): if a feed is already stored, THIS
|
||||
// completion is the redundant one — release its feed rather than overwriting
|
||||
// the stored id and leaking the already-tracked subscription.
|
||||
if (_alarmSubscriptionIds.ContainsKey(msg.SourceReference))
|
||||
{
|
||||
if (_adapter is IAlarmSubscribableConnection alarmable)
|
||||
{
|
||||
_log.Warning(
|
||||
"[{0}] Duplicate alarm feed for source {1}; releasing the redundant " +
|
||||
"subscription instead of overwriting the stored one.",
|
||||
_connectionName, msg.SourceReference);
|
||||
_ = alarmable.UnsubscribeAlarmsAsync(msg.SubscriptionId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_alarmSubscriptionIds[msg.SourceReference] = msg.SubscriptionId;
|
||||
_log.Info("[{0}] Alarm feed subscribed for source {1}", _connectionName, msg.SourceReference);
|
||||
}
|
||||
}
|
||||
else if (!msg.Success)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user