Skip to content

Commit 5bbbc6b

Browse files
satheeshaGowdaSatheesha Chattenahalli Hanume Gowda
andauthored
Add shard id field to CLUSTER SHARDS response (valkey-io#2568)
This change exposes an existing, persistent (in nodes.conf) unique shard identifier for each shard in the cluster as part of the `CLUSTER SHARDS` command response. ``` 1) 1) "slots" 2) 1) (integer) 0 2) (integer) 999 3) (integer) 2001 4) (integer) 3999 5) (integer) 4501 6) (integer) 5460 3) "nodes" 4) 1) 1) "id" 2) "6e76043bed00e716e85035107866ea16e9a5f700" 3) "port" 4) (integer) 6385 5) "ip" 6) "127.0.0.1" 7) "endpoint" 8) "127.0.0.1" 9) "role" 10) "replica" 11) "replication-offset" 12) (integer) 8092 13) "health" 14) "online" 2) 1) "id" 2) "b2f8c841707b2246ec2a641c37f16e88fe0bb700" 3) "port" 4) (integer) 6380 5) "ip" 6) "127.0.0.1" 7) "endpoint" 8) "127.0.0.1" 9) "role" 10) "master" 11) "replication-offset" 12) (integer) 8092 13) "health" 14) "online" 5) "id" 6) "3f2a7bb7bbd5fc2a331fe9bf95f5e02bcca02430" ``` --------- Signed-off-by: Satheesha Chattenahalli Hanume Gowda <satheesha@apple.com> Co-authored-by: Satheesha Chattenahalli Hanume Gowda <satheesha@apple.com>
1 parent 22247f6 commit 5bbbc6b

4 files changed

Lines changed: 47 additions & 6 deletions

File tree

src/cluster_legacy.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6909,9 +6909,11 @@ void addNodeDetailsToShardReply(client *c, clusterNode *node) {
69096909
setDeferredMapLen(c, node_replylen, reply_count);
69106910
}
69116911

6912-
/* Add to the output buffer of the given client, an array of slot (start, end)
6913-
* pair owned by the shard, also the primary and set of replica(s) along with
6914-
* information about each node. */
6912+
/* Add to the output buffer of the given client,
6913+
* an array of slot (start, end) pair owned by the shard,
6914+
* an array of the primary and set of replica(s) along with information about each node,
6915+
* and shard id.
6916+
*/
69156917
void clusterCommandShards(client *c) {
69166918
addReplyArrayLen(c, dictSize(server.cluster->shards));
69176919
/* This call will add slot_info_pairs to all nodes */
@@ -6920,7 +6922,7 @@ void clusterCommandShards(client *c) {
69206922
for (dictEntry *de = dictNext(di); de != NULL; de = dictNext(di)) {
69216923
list *nodes = dictGetVal(de);
69226924
serverAssert(listLength(nodes) > 0);
6923-
addReplyMapLen(c, 2);
6925+
addReplyMapLen(c, 3);
69246926
addReplyBulkCString(c, "slots");
69256927

69266928
/* Find a node which has the slot information served by this shard. */
@@ -6953,6 +6955,8 @@ void clusterCommandShards(client *c) {
69536955
addNodeDetailsToShardReply(c, n);
69546956
clusterFreeNodesSlotsInfo(n);
69556957
}
6958+
addReplyBulkCString(c, "id");
6959+
addReplyBulkCBuffer(c, dictGetKey(de), CLUSTER_NAMELEN);
69566960
}
69576961
dictReleaseIterator(di);
69586962
}

src/commands.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,9 @@ struct COMMAND_ARG CLUSTER_SETSLOT_Args[] = {
10061006

10071007
#ifndef SKIP_CMD_HISTORY_TABLE
10081008
/* CLUSTER SHARDS history */
1009-
#define CLUSTER_SHARDS_History NULL
1009+
commandHistory CLUSTER_SHARDS_History[] = {
1010+
{"9.0.0","Added shard id field to CLUSTER SHARDS response"},
1011+
};
10101012
#endif
10111013

10121014
#ifndef SKIP_CMD_TIPS_TABLE
@@ -1165,7 +1167,7 @@ struct COMMAND_STRUCT CLUSTER_Subcommands[] = {
11651167
{MAKE_CMD("saveconfig","Forces a node to save the cluster configuration to disk.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SAVECONFIG_History,0,CLUSTER_SAVECONFIG_Tips,0,clusterCommand,2,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE,0,CLUSTER_SAVECONFIG_Keyspecs,0,NULL,0)},
11661168
{MAKE_CMD("set-config-epoch","Sets the configuration epoch for a new node.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SET_CONFIG_EPOCH_History,0,CLUSTER_SET_CONFIG_EPOCH_Tips,0,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE,0,CLUSTER_SET_CONFIG_EPOCH_Keyspecs,0,NULL,1),.args=CLUSTER_SET_CONFIG_EPOCH_Args},
11671169
{MAKE_CMD("setslot","Binds a hash slot to a node.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SETSLOT_History,1,CLUSTER_SETSLOT_Tips,0,clusterCommand,-4,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE|CMD_MAY_REPLICATE,0,CLUSTER_SETSLOT_Keyspecs,0,NULL,3),.args=CLUSTER_SETSLOT_Args},
1168-
{MAKE_CMD("shards","Returns the mapping of cluster slots to shards.","O(N) where N is the total number of cluster nodes","7.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SHARDS_History,0,CLUSTER_SHARDS_Tips,1,clusterCommand,2,CMD_LOADING|CMD_STALE,0,CLUSTER_SHARDS_Keyspecs,0,NULL,0)},
1170+
{MAKE_CMD("shards","Returns the mapping of cluster slots to shards.","O(N) where N is the total number of cluster nodes","7.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SHARDS_History,1,CLUSTER_SHARDS_Tips,1,clusterCommand,2,CMD_LOADING|CMD_STALE,0,CLUSTER_SHARDS_Keyspecs,0,NULL,0)},
11691171
{MAKE_CMD("slaves","Lists the replica nodes of a primary node.","O(N) where N is the number of replicas.","3.0.0",CMD_DOC_DEPRECATED,"`CLUSTER REPLICAS`","5.0.0","cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SLAVES_History,0,CLUSTER_SLAVES_Tips,1,clusterCommand,3,CMD_ADMIN|CMD_STALE,0,CLUSTER_SLAVES_Keyspecs,0,NULL,1),.args=CLUSTER_SLAVES_Args},
11701172
{MAKE_CMD("slot-stats","Return an array of slot usage statistics for slots assigned to the current node.","O(N) where N is the total number of slots based on arguments. O(N*log(N)) with ORDERBY subcommand.","8.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SLOT_STATS_History,0,CLUSTER_SLOT_STATS_Tips,2,clusterSlotStatsCommand,-4,CMD_STALE|CMD_LOADING,0,CLUSTER_SLOT_STATS_Keyspecs,0,NULL,1),.args=CLUSTER_SLOT_STATS_Args},
11711173
{MAKE_CMD("slots","Returns the mapping of cluster slots to nodes.","O(N) where N is the total number of Cluster nodes","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SLOTS_History,2,CLUSTER_SLOTS_Tips,1,clusterCommand,2,CMD_LOADING|CMD_STALE,0,CLUSTER_SLOTS_Keyspecs,0,NULL,0)},

src/commands/cluster-shards.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
"arity": 2,
88
"container": "CLUSTER",
99
"function": "clusterCommand",
10+
"history": [
11+
[
12+
"9.0.0",
13+
"Added shard id field to CLUSTER SHARDS response"
14+
]
15+
],
1016
"command_flags": [
1117
"LOADING",
1218
"STALE"
@@ -81,6 +87,10 @@
8187
}
8288
}
8389
}
90+
},
91+
"id": {
92+
"description": "A unique shard identifier.",
93+
"type": "string"
8494
}
8595
}
8696
}

tests/cluster/tests/28-cluster-shards.tcl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,28 @@ test "CLUSTER MYSHARDID reports same shard id after cluster restart" {
285285
assert_equal [dict get $node_ids $i] [R $i cluster myshardid]
286286
}
287287
}
288+
289+
test "CLUSTER SHARDS id response validation" {
290+
# For each node in the cluster
291+
for {set i 0} {$i < $::cluster_master_nodes + $::cluster_replica_nodes} {incr i} {
292+
# Get the CLUSTER SHARDS output from this node
293+
set shards [R $i CLUSTER SHARDS]
294+
set seen_shard_ids {}
295+
296+
# For each shard in the output
297+
foreach shard $shards {
298+
set shard_dict [dict create {*}$shard]
299+
300+
# 1. Verify 'id' key exists
301+
assert {[dict exists $shard_dict id]}
302+
set shard_id [dict get $shard_dict id]
303+
304+
# 2. Verify shard_id is a 40-char string
305+
assert {[string length $shard_id] == 40}
306+
307+
# 3. Verify that for a given node's output, all shard IDs are unique
308+
assert {[dict exists $seen_shard_ids $shard_id] == 0}
309+
dict set seen_shard_ids $shard_id 1
310+
}
311+
}
312+
}

0 commit comments

Comments
 (0)