feat(mesh): ClusterRoleInfo exposes the node's own cluster-scoped role

Phase 6 Task 1. IClusterRoleInfo gains ClusterRole/ClusterId, derived from
the node's configured AkkaClusterOptions.Roles at construction time (not
live Cluster.State) so the identity is available before the cluster forms.
First cluster-scoped role wins when more than one is configured, logged as
a Warning. Updates the FakeClusterRoleInfo test double in
ServiceCollectionExtensionsTests to satisfy the new interface members.

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-24 01:17:58 -04:00
parent 87ff00fd30
commit 2d2f1decae
4 changed files with 149 additions and 0 deletions
@@ -14,6 +14,21 @@ public interface IClusterRoleInfo
NodeId LocalNode { get; }
/// <summary>Gets the set of roles assigned to the local node.</summary>
IReadOnlySet<string> LocalRoles { get; }
/// <summary>
/// Gets the local node's cluster-scoped role (e.g. <c>cluster-SITE-A</c>), or <c>null</c> when
/// the node carries none. Derived from the node's OWN configured roles at construction time —
/// NOT from live cluster membership — so it is available before the cluster forms (per-cluster
/// mesh, Phase 6). When more than one cluster-scoped role is configured, the first one wins.
/// </summary>
string? ClusterRole { get; }
/// <summary>
/// Gets the ClusterId extracted from <see cref="ClusterRole"/> (e.g. <c>SITE-A</c>), or
/// <c>null</c> when the node carries no cluster-scoped role.
/// </summary>
string? ClusterId { get; }
/// <summary>Checks if the local node has the specified role.</summary>
/// <param name="role">Role name to check.</param>
/// <returns>True if the local node has the role; otherwise, false.</returns>