refactor(inbound-api): use the shared ZB.MOM.WW.Health IActiveNodeGate (ScadaBridge#80)
The InboundAPI carried its own IActiveNodeGate (implemented by Host/Health/ActiveNodeGate) whose rule already matched the shared Health 0.3.0 AkkaActiveNodeGate — both route to ClusterActiveNode (oldest Up member). The private interface and implementation are deleted; InboundAPI references ZB.MOM.WW.Health (0.3.0, already pinned) and InboundApiEndpointFilter, AuditWriteMiddleware, InboundMethodWarmupService and FlowDebugRunner consume ZB.MOM.WW.Health.IActiveNodeGate. The Central branch of Program.cs registers AkkaActiveNodeGate (unscoped, like the active-node health check). Warm-up behaviour is kept: the shared gate answers false while no ActorSystem resolves, while this member is not Up, and on any cluster-init fault. It resolves the ActorSystem through the existing DI singleton bridge (GetOrCreateActorSystem), the same path the health probes use. Tests: CompositionRoot asserts the shared gate type (fails with the registration removed); the evaluator wiring test now drives AkkaActiveNodeGate; new warm-up test (no ActorSystem -> not active). Nothing was missing from the Health 0.3.0 package. (ScadaBridge#80) Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -93,7 +93,12 @@ akka {{
|
||||
while (cluster.SelfMember.Status != Akka.Cluster.MemberStatus.Up && DateTime.UtcNow < deadline)
|
||||
await Task.Delay(100);
|
||||
|
||||
var gate = new ActiveNodeGate(akkaService);
|
||||
// Gitea #80: the inbound API's gate is the shared AkkaActiveNodeGate, resolving the
|
||||
// ActorSystem from DI exactly as Program.cs's singleton bridge serves it.
|
||||
using var sp = new ServiceCollection()
|
||||
.AddSingleton(_ => akkaService.GetOrCreateActorSystem())
|
||||
.BuildServiceProvider();
|
||||
var gate = new ZB.MOM.WW.Health.Akka.AkkaActiveNodeGate(sp);
|
||||
var provider = new AkkaClusterNodeProvider(akkaService, "Central");
|
||||
Assert.True(gate.IsActiveNode);
|
||||
Assert.True(provider.SelfIsPrimary);
|
||||
@@ -104,6 +109,17 @@ akka {{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gitea #80 warm-up contract: while no ActorSystem is available the shared gate reports
|
||||
/// standby, never active — the safe default the retired ScadaBridge gate also had.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ActiveNodeGate_WithoutActorSystem_IsNotActive()
|
||||
{
|
||||
using var sp = new ServiceCollection().BuildServiceProvider();
|
||||
Assert.False(new ZB.MOM.WW.Health.Akka.AkkaActiveNodeGate(sp).IsActiveNode);
|
||||
}
|
||||
|
||||
private static int FreePort()
|
||||
{
|
||||
var l = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Loopback, 0);
|
||||
|
||||
@@ -332,7 +332,7 @@ public class CentralCompositionRootTests : IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// Regression test: the Central composition root MUST register a
|
||||
/// concrete <see cref="IActiveNodeGate"/> implementation. Without it,
|
||||
/// concrete <see cref="ZB.MOM.WW.Health.IActiveNodeGate"/> implementation. Without it,
|
||||
/// <see cref="InboundApiEndpointFilter"/> falls through to "allow" and a
|
||||
/// standby central node continues to serve the inbound API, racing the
|
||||
/// active node and executing scripts against stale singleton state. The
|
||||
@@ -344,12 +344,17 @@ public class CentralCompositionRootTests : IDisposable
|
||||
/// indistinguishable from "missing" at runtime, which is the failure mode
|
||||
/// the finding describes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Gitea #80: the gate is the shared <see cref="ZB.MOM.WW.Health.IActiveNodeGate"/> backed by
|
||||
/// <see cref="ZB.MOM.WW.Health.Akka.AkkaActiveNodeGate"/> — the same ClusterActiveNode rule as
|
||||
/// the /health/active probe — not a ScadaBridge-private seam.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public void Central_IActiveNodeGate_IsRegisteredAsActiveNodeGate()
|
||||
{
|
||||
var gate = _factory.Services.GetService<IActiveNodeGate>();
|
||||
var gate = _factory.Services.GetService<ZB.MOM.WW.Health.IActiveNodeGate>();
|
||||
Assert.NotNull(gate);
|
||||
Assert.IsType<ActiveNodeGate>(gate);
|
||||
Assert.IsType<ZB.MOM.WW.Health.Akka.AkkaActiveNodeGate>(gate);
|
||||
}
|
||||
|
||||
// --- ScadaBridge#22 regression ---
|
||||
|
||||
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Health;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.InboundAPI.Tests;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NSubstitute;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.InboundApi;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
|
||||
using ZB.MOM.WW.Health;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.InboundAPI.Tests;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
||||
using ZB.MOM.WW.ScadaBridge.InboundAPI.Middleware;
|
||||
using ZB.MOM.WW.Health;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.InboundAPI.Tests.Middleware;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using ZB.MOM.WW.ScadaBridge.AuditLog.Configuration;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;
|
||||
using ZB.MOM.WW.ScadaBridge.InboundAPI.Middleware;
|
||||
using ZB.MOM.WW.Health;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.InboundAPI.Tests;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.Health;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.InboundAPI.Tests;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Flattening;
|
||||
using ZB.MOM.WW.ScadaBridge.DeploymentManager;
|
||||
using ZB.MOM.WW.ScadaBridge.InboundAPI;
|
||||
using ZB.MOM.WW.ScadaBridge.ManagementService.FlowDebug;
|
||||
using ZB.MOM.WW.Health;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.ManagementService.Tests;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user