diff --git a/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/ActiveNodeHealthCheck.cs b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/ActiveNodeHealthCheck.cs
index 97c1801..a9b54d3 100644
--- a/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/ActiveNodeHealthCheck.cs
+++ b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/ActiveNodeHealthCheck.cs
@@ -1,8 +1,11 @@
+using System.Runtime.CompilerServices;
using Akka.Actor;
using Akka.Cluster;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
+[assembly: InternalsVisibleTo("ZB.MOM.WW.Health.Akka.Tests")]
+
namespace ZB.MOM.WW.Health.Akka;
///
@@ -10,7 +13,7 @@ namespace ZB.MOM.WW.Health.Akka;
/// so the role-less and role-filtered matrices are exhaustively
/// table-testable without forming a real cluster.
///
-public static class ActiveNodeDecision
+internal static class ActiveNodeDecision
{
///
/// Maps the resolved cluster facts to a .
@@ -87,7 +90,8 @@ public sealed class ActiveNodeHealthCheck : IHealthCheck
public ActiveNodeHealthCheck(IServiceProvider serviceProvider, string role)
{
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
- _role = role ?? throw new ArgumentNullException(nameof(role));
+ ArgumentException.ThrowIfNullOrWhiteSpace(role);
+ _role = role;
}
///
@@ -119,15 +123,26 @@ public sealed class ActiveNodeHealthCheck : IHealthCheck
}
var health = ActiveNodeDecision.Evaluate(selfUp, isLeader, hasRole, _role);
- return Task.FromResult(new HealthCheckResult(health, DescribeResult(health, self.Status)));
+ var description = DescribeResult(health, self.Status, selfUp, isLeader);
+ var result = health switch
+ {
+ HealthStatus.Healthy => HealthCheckResult.Healthy(description),
+ HealthStatus.Degraded => HealthCheckResult.Degraded(description),
+ _ => HealthCheckResult.Unhealthy(description),
+ };
+ return Task.FromResult(result);
}
- private string DescribeResult(HealthStatus health, MemberStatus status)
+ private string DescribeResult(HealthStatus health, MemberStatus status, bool selfUp, bool isLeader)
{
if (_role is null)
- return health == HealthStatus.Healthy
- ? "Active node (cluster leader)."
- : $"Standby node (status: {status}).";
+ {
+ if (health == HealthStatus.Healthy)
+ return "Active node (cluster leader).";
+ return selfUp && !isLeader
+ ? "Standby: node is Up but not the cluster leader."
+ : $"Standby: node is not Up (status: {status}).";
+ }
return health switch
{
diff --git a/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs
index 3deab3c..74e040b 100644
--- a/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs
+++ b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs
@@ -45,7 +45,12 @@ public sealed class AkkaClusterHealthCheck : IHealthCheck
var status = Cluster.Get(system).SelfMember.Status;
var health = _policy.Evaluate(status);
var description = $"Akka cluster member status: {status}";
-
- return Task.FromResult(new HealthCheckResult(health, description));
+ var result = health switch
+ {
+ HealthStatus.Healthy => HealthCheckResult.Healthy(description),
+ HealthStatus.Degraded => HealthCheckResult.Degraded(description),
+ _ => HealthCheckResult.Unhealthy(description),
+ };
+ return Task.FromResult(result);
}
}
diff --git a/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/ActiveNodeDecisionTests.cs b/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/ActiveNodeDecisionTests.cs
index 1296376..7659ba0 100644
--- a/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/ActiveNodeDecisionTests.cs
+++ b/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/ActiveNodeDecisionTests.cs
@@ -31,7 +31,7 @@ public sealed class ActiveNodeDecisionTests
// Role-filtered: requiredRole != null.
// lacks role -> Healthy (probe irrelevant for this node)
- // has role & is leader -> Healthy
+ // has role & is leader -> Healthy (selfUp is ignored — role-filtered mode only cares about leadership)
// has role & not leader -> Degraded
public static IEnumerable