fix(health): akka check uses the shared SPEC Default policy, not Degraded-only OtOpcUaCompat (lmxopcua#771)
OtOpcUaCompat was a migration shim (1d729fb0) preserving the pre-adoption
two-way mapping; nothing depends on it. A node that is not a live cluster
member now fails /health/ready.
Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -84,7 +84,11 @@ public static class HealthEndpoints
|
||||
"akka",
|
||||
failureStatus: null,
|
||||
tags: new[] { ZbHealthTags.Ready, ZbHealthTags.Active },
|
||||
args: AkkaClusterStatusPolicy.OtOpcUaCompat)
|
||||
// Shared SPEC Default policy (lmxopcua#771). OtOpcUaCompat was a migration shim that kept the
|
||||
// pre-adoption two-way behaviour (anything not Up = Degraded), which can never fail /health/ready
|
||||
// — Degraded passes. Nothing relies on that: Down/Removed/Joining-failed now answer 503 on the
|
||||
// ready tier, Leaving/Exiting stay Degraded (a draining node keeps serving).
|
||||
args: AkkaClusterStatusPolicy.Default)
|
||||
// "Is this node in charge of its mesh?" — Healthy on the one node that owns the active
|
||||
// work for its Cluster, Unhealthy (503) on its partner, so Traefik pins the AdminUI to the
|
||||
// node actually hosting the cluster singletons.
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using Akka.Actor;
|
||||
using Akka.Configuration;
|
||||
using Akka.TestKit.Xunit2;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -92,3 +95,31 @@ public sealed class ActiveTierRegistrationTests
|
||||
ClusterPrimaryRegistration(hasAdmin: true).Tags.ShouldNotContain(ZbHealthTags.Ready);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>lmxopcua#771 — the akka check must use the shared SPEC Default policy so a node that is not a live
|
||||
/// cluster member makes <c>/health/ready</c> fail (the retired OtOpcUaCompat policy could only say Degraded).</summary>
|
||||
public sealed class AkkaReadyPolicyTests : TestKit
|
||||
{
|
||||
public AkkaReadyPolicyTests()
|
||||
: base(ConfigurationFactory.ParseString(
|
||||
"akka.actor.provider = cluster\nakka.remote.dot-netty.tcp.port = 0\nakka.remote.dot-netty.tcp.hostname = 127.0.0.1"))
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Akka_check_is_Unhealthy_when_self_has_not_joined_a_cluster()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<ActorSystem>(Sys);
|
||||
services.AddOtOpcUaHealth(hasAdmin: true);
|
||||
var sp = services.BuildServiceProvider();
|
||||
var registration = sp.GetRequiredService<IOptions<HealthCheckServiceOptions>>()
|
||||
.Value.Registrations.Single(r => r.Name == "akka");
|
||||
registration.Tags.ShouldContain(ZbHealthTags.Ready);
|
||||
|
||||
var result = await registration.Factory(sp).CheckHealthAsync(
|
||||
new HealthCheckContext { Registration = registration }, CancellationToken.None);
|
||||
|
||||
result.Status.ShouldBe(HealthStatus.Unhealthy);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user