test(archreview #10): cover actor-context preservation through the REAL CapabilityInvoker
The pass-through NullDriverCapabilityInvoker returns the call-site task directly, so it never exercises the real invoker's internal `pipeline.ExecuteAsync(...).ConfigureAwait(false)`. Adds a test-only Core reference to Runtime.Tests (the PRODUCTION Runtime assembly stays Polly-free via the seam) and a discovery test that drives DriverInstanceActor through a real CapabilityInvoker over a genuinely-yielding ITagDiscovery driver — proving the invoker's internal ConfigureAwait(false) does NOT leak to the actor's own await, so the post-await Context.Parent.Tell still runs (DiscoveredNodesReady arrives). Runtime.Tests 358, Core.Tests 238.
This commit is contained in:
+33
@@ -2,6 +2,7 @@ using Akka.Actor;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Resilience;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
|
||||
using ZB.MOM.WW.OtOpcUa.Runtime.Tests.Harness;
|
||||
|
||||
@@ -144,6 +145,38 @@ public sealed class DriverInstanceActorDiscoveryTests : RuntimeActorTestBase
|
||||
published.DriverInstanceId.ShouldBe(driver.DriverInstanceId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arch-review #10: the SAME async-discovery context-preservation guarantee, but driven through the
|
||||
/// REAL <see cref="CapabilityInvoker"/> — whose Polly pipeline is awaited with
|
||||
/// <c>ConfigureAwait(false)</c> internally. This is the one path the pass-through
|
||||
/// <c>NullDriverCapabilityInvoker</c> (used by the sibling test) cannot cover: it returns the
|
||||
/// call-site task directly, so it never exercises the invoker's internal off-context await. If that
|
||||
/// internal <c>ConfigureAwait(false)</c> leaked to the actor's own <c>await _invoker.ExecuteAsync(…)</c>,
|
||||
/// the post-await <c>Context.Parent.Tell</c> in <c>HandleRediscoverAsync</c> would fault with
|
||||
/// "no active ActorContext" and no message would arrive. Its arrival proves the actor context survives
|
||||
/// the real resilience pipeline.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Async_discovery_through_real_CapabilityInvoker_preserves_actor_context()
|
||||
{
|
||||
var pipelineBuilder = new DriverResiliencePipelineBuilder(); // real Polly pipeline, tier-A defaults
|
||||
var invoker = new CapabilityInvoker(
|
||||
pipelineBuilder,
|
||||
driverInstanceId: "yielding-discoverable",
|
||||
optionsAccessor: () => new DriverResilienceOptions { Tier = DriverTier.A },
|
||||
driverType: "Stub");
|
||||
var driver = new YieldingDiscoverableStubDriver();
|
||||
var parent = CreateTestProbe();
|
||||
var actor = parent.ChildActorOf(DriverInstanceActor.Props(
|
||||
driver, rediscoverInterval: TimeSpan.FromMilliseconds(20), invoker: invoker));
|
||||
|
||||
actor.Tell(new DriverInstanceActor.InitializeRequested("{}"));
|
||||
|
||||
var published = parent.ExpectMsg<DriverInstanceActor.DiscoveredNodesReady>(TimeSpan.FromSeconds(5));
|
||||
published.Nodes.Count.ShouldBe(3);
|
||||
published.DriverInstanceId.ShouldBe(driver.DriverInstanceId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The attempt cap bounds a discovered set that never stabilises: a driver whose set keeps GROWING
|
||||
/// (1,2,3,…) never repeats its signature, so the loop is stopped only by
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Server\ZB.MOM.WW.OtOpcUa.Runtime\ZB.MOM.WW.OtOpcUa.Runtime.csproj"/>
|
||||
<!-- TEST-ONLY reference to Core (Polly): lets the resilience-wiring guards construct the REAL
|
||||
CapabilityInvoker. The PRODUCTION Runtime assembly stays Polly-free (consumes the
|
||||
IDriverCapabilityInvoker seam) — this reference is in the test project only. -->
|
||||
<ProjectReference Include="..\..\..\src\Core\ZB.MOM.WW.OtOpcUa.Core\ZB.MOM.WW.OtOpcUa.Core.csproj"/>
|
||||
<ProjectReference Include="..\..\..\src\Core\ZB.MOM.WW.OtOpcUa.Configuration\ZB.MOM.WW.OtOpcUa.Configuration.csproj"/>
|
||||
<ProjectReference Include="..\..\..\src\Core\ZB.MOM.WW.OtOpcUa.Commons\ZB.MOM.WW.OtOpcUa.Commons.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user