Skip to main content

Cluster inspection

The Server facet exposes typed, read-only Cluster inspection. An ordinary call reports one execution node's view. It does not replace the client's slot map, deduplicate a global topology, configure Cluster membership, or enable Cluster mode on a standalone server. AllowAdmin is not required; the server still enforces ACL permissions.

APIRedis commandMinimum Redis version
ClusterInfoAsyncCLUSTER INFO3.0
ClusterNodesAsyncCLUSTER NODES3.0
ClusterShardsAsyncCLUSTER SHARDS7.0
ClusterLinksAsyncCLUSTER LINKS7.0
ClusterMyIdAsyncCLUSTER MYID3.0
ClusterMyShardIdAsyncCLUSTER MYSHARDID7.2
ClusterKeySlotAsyncCLUSTER KEYSLOT3.0
ClusterCountKeysInSlotAsyncCLUSTER COUNTKEYSINSLOT3.0
ClusterSlotStatsAsyncCLUSTER SLOT-STATS SLOTSRANGE8.2
ClusterSlotStatsByMetricAsyncCLUSTER SLOT-STATS ORDERBY8.2

Unsupported commands and standalone-server failures remain RespireServerException. No fallback fabricates a topology or returns an empty success. Redis 7.0 and 8.4 Cluster tests cover RESP2 and RESP3, including explicit errors for newer commands against Redis 7.0. Standalone tests cover preserved server errors.

RespireClusterInfo info = await redis.Server.ClusterInfoAsync();
ulong? currentEpoch = info.CurrentEpoch;
ulong? localEpoch = info.MyEpoch;
Console.WriteLine($"Current epoch: {currentEpoch}; local epoch: {localEpoch}");
RespireClusterShard[] shards = await redis.Server.ClusterShardsAsync();
foreach (var shard in shards)
{
foreach (var member in shard.Nodes)
Console.WriteLine($"{member.Id}: {member.Role}, {member.Health}, {member.Endpoint}");
}

Owned node views​

RespireClusterInfo exposes common counters and retains all report fields in Attributes. RespireClusterNode retains advertised address text, flags, primary ID, timing/epoch counters, link state, inclusive slot ranges, and importing/migrating slot annotations. Unknown trailing tokens remain in AdditionalTokens. An address such as :0@0 is retained for inspection even when it cannot be used for a connection.

RespireClusterInfo.CurrentEpoch and MyEpoch are ulong? and preserve the full unsigned 64-bit epoch range, including values above long.MaxValue. Missing epoch fields remain null. This corrects their earlier long? type: callers that store or construct these values using signed locals must migrate those locals to ulong?. The other INFO counters remain nonnegative long? values; their signed limits do not change. Attributes retains the original text of known and unknown fields. See the Redis Cluster epoch specification.

Shard models contain slot ranges and member nodes. Endpoint, IP, hostname, plain port, and TLS port remain distinct. Null, empty, and ? endpoints are preserved; a zero port means unavailable. The client does not turn these advertised values into reachable endpoints or infer missing addresses. Role and health strings preserve future values. See Redis's SHARDS and NODES references.

Link models describe Cluster bus connections, including direction, peer ID, Unix millisecond creation time, event flags, and buffer sizes. They do not represent the client's own connections. See CLUSTER LINKS.

Structured models retain unknown fields in AdditionalFields. Those RespireResult values are recursively copied into GC-owned storage; disposal is optional and invalidates their element views. Other models need no disposal. All results remain valid after the reply and client are disposed.

Each call returns its own snapshot; inspection results are not shared cached topology. Array members are caller-owned and mutable. Record equality compares array references, not their elements; compare elements explicitly when comparing snapshots.

Keys, slots, and statistics​

ClusterKeySlotAsync applies the client view's key prefix and preserves binary key bytes. It asks the execution node to calculate that key's slot; it does not route to the key owner. Numeric slot arguments are literal numbers, validated in 0–16383. Ranges are inclusive and cannot be reversed.

ClusterCountKeysInSlotAsync counts keys on the execution node, even if another node owns the slot. Use the all-node variant to compare node-local counts. Summing replica and primary counts can count the same data more than once.

int slot = await redis.Server.ClusterKeySlotAsync("orders:42");
RespireClusterSlotStats[] local = await redis.Server.ClusterSlotStatsAsync(slot, slot);
RespireClusterSlotStats[] busiest = await redis.Server.ClusterSlotStatsByMetricAsync(
RespireClusterSlotMetric.KeyCount, limit: 10, descending: true);

SLOT-STATS returns slots belonging to the queried node's shard. Range results retain server order. Metric results default to descending order, with optional limits from 1 through 16384. KeyCount is always present; other metrics are nullable when disabled by server configuration. Ordering by an unavailable metric surfaces the server error. These APIs do not enable statistics collection. See CLUSTER SLOT-STATS for metric configuration and ordering semantics.

Results from every node​

Every method has an OnAllNodesAsync counterpart with the same arguments. Discovery includes replicas and members without assigned slots. Each RespireServerResult<T> contains its endpoint and either an owned value or the original failure. Standalone clients query their one endpoint; Cluster-only commands still fail on that server. Without UseCluster, discovery queries only that connected endpoint even if the server belongs to a Cluster. Discovery itself requires permission to execute CLUSTER NODES.

var results = await redis.Server.ClusterShardsOnAllNodesAsync();
foreach (var result in results)
{
if (result.IsSuccess)
Console.WriteLine($"{result.Endpoint}: {result.Value.Length} reported shards");
else
Console.WriteLine($"{result.Endpoint}: {result.Error!.Message}");
}

Inspect every result. Node views may overlap or disagree during failover; no merge or deduplication is implied. Cancellation during discovery throws. After discovery it is attributed to affected nodes while completed successes remain available.

These 20 methods extend IServerCommands; external implementations, decorators, and mocks must implement or forward them. They are immediate inspection APIs and do not add batch or transaction methods.