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:
@@ -279,6 +279,41 @@ public class RouteHelperTests
|
||||
Assert.True(seen.IsCancellationRequested); // the client-abort token cancels the wait
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WaitForAttribute_SlowTimedOutResponse_NotPreemptedByLocalBackstop()
|
||||
{
|
||||
// InboundAPI-031: WaitForAttribute must NOT impose a local wait-timeout backstop.
|
||||
// The site enforces the wait timeout and returns Matched=false; the round trip is
|
||||
// bounded by CommunicationService's Ask (timeout + IntegrationTimeout). A local CTS
|
||||
// of `timeout + small grace` (the prior InboundAPI-029 approach) was TIGHTER than
|
||||
// that round-trip budget, so a slow-but-valid timed-out response would be cancelled
|
||||
// into an exception (a 500) instead of the spec §6 `false`. With the backstop
|
||||
// removed, a response arriving well after the (tiny) wait timeout still returns a
|
||||
// clean `false`, and the token the router observed was never cancelled by RouteHelper
|
||||
// — if a tight local backstop were reintroduced, the honoured token below would throw.
|
||||
SiteResolves("inst-1", "SiteA");
|
||||
CancellationToken seen = default;
|
||||
_router.RouteToWaitForAttributeAsync("SiteA", Arg.Any<RouteToWaitForAttributeRequest>(), Arg.Do<CancellationToken>(t => seen = t))
|
||||
.Returns(async ci =>
|
||||
{
|
||||
var token = (CancellationToken)ci[2];
|
||||
// Simulate the site enforcing the wait + a round trip far longer than the
|
||||
// tiny wait timeout; honour the token so a (re)introduced local backstop
|
||||
// would surface here as an OperationCanceledException.
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(400), token);
|
||||
return new RouteToWaitForAttributeResponse(
|
||||
((RouteToWaitForAttributeRequest)ci[1]).CorrelationId,
|
||||
Matched: false, Value: null, Quality: null, TimedOut: true,
|
||||
Success: true, ErrorMessage: null, DateTimeOffset.UtcNow);
|
||||
});
|
||||
|
||||
var matched = await CreateHelper().To("inst-1")
|
||||
.WaitForAttribute("Flag", true, TimeSpan.FromMilliseconds(20));
|
||||
|
||||
Assert.False(matched); // clean spec §6 false, not a cancellation
|
||||
Assert.False(seen.IsCancellationRequested); // no local wait-timeout backstop fired
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WaitForAttribute_WithParentExecutionId_CarriesItOnRequest()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user