Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/cluster_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -6906,9 +6906,11 @@ void addNodeDetailsToShardReply(client *c, clusterNode *node) {
setDeferredMapLen(c, node_replylen, reply_count);
}

/* Add to the output buffer of the given client, an array of slot (start, end)
* pair owned by the shard, also the primary and set of replica(s) along with
* information about each node. */
/* Add to the output buffer of the given client,
* an array of slot (start, end) pair owned by the shard,
* an array of the primary and set of replica(s) along with information about each node,
* and shard id.
*/
void clusterCommandShards(client *c) {
addReplyArrayLen(c, dictSize(server.cluster->shards));
/* This call will add slot_info_pairs to all nodes */
Expand All @@ -6917,7 +6919,7 @@ void clusterCommandShards(client *c) {
for (dictEntry *de = dictNext(di); de != NULL; de = dictNext(di)) {
list *nodes = dictGetVal(de);
serverAssert(listLength(nodes) > 0);
addReplyMapLen(c, 2);
addReplyMapLen(c, 3);
addReplyBulkCString(c, "slots");

/* Find a node which has the slot information served by this shard. */
Expand Down Expand Up @@ -6950,6 +6952,8 @@ void clusterCommandShards(client *c) {
addNodeDetailsToShardReply(c, n);
clusterFreeNodesSlotsInfo(n);
}
addReplyBulkCString(c, "id");
addReplyBulkCBuffer(c, dictGetKey(de), CLUSTER_NAMELEN);
}
dictReleaseIterator(di);
}
Expand Down
6 changes: 4 additions & 2 deletions src/commands.def
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,9 @@ struct COMMAND_ARG CLUSTER_SETSLOT_Args[] = {

#ifndef SKIP_CMD_HISTORY_TABLE
/* CLUSTER SHARDS history */
#define CLUSTER_SHARDS_History NULL
commandHistory CLUSTER_SHARDS_History[] = {
{"9.0.0","Added shard id field to CLUSTER SHARDS response"},
};
#endif

#ifndef SKIP_CMD_TIPS_TABLE
Expand Down Expand Up @@ -1165,7 +1167,7 @@ struct COMMAND_STRUCT CLUSTER_Subcommands[] = {
{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)},
{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},
{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},
{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)},
{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)},
{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},
{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},
{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)},
Expand Down
10 changes: 10 additions & 0 deletions src/commands/cluster-shards.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
"arity": 2,
"container": "CLUSTER",
"function": "clusterCommand",
"history": [
[
"9.0.0",
"Added shard id field to CLUSTER SHARDS response"
]
],
"command_flags": [
"LOADING",
"STALE"
Expand Down Expand Up @@ -81,6 +87,10 @@
}
}
}
},
"id": {
"description": "A unique shard identifier.",
"type": "string"
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions tests/cluster/tests/28-cluster-shards.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,28 @@ test "CLUSTER MYSHARDID reports same shard id after cluster restart" {
assert_equal [dict get $node_ids $i] [R $i cluster myshardid]
}
}

test "CLUSTER SHARDS id response validation" {
# For each node in the cluster
for {set i 0} {$i < $::cluster_master_nodes + $::cluster_replica_nodes} {incr i} {
# Get the CLUSTER SHARDS output from this node
set shards [R $i CLUSTER SHARDS]
set seen_shard_ids {}

# For each shard in the output
foreach shard $shards {
set shard_dict [dict create {*}$shard]

# 1. Verify 'id' key exists
assert {[dict exists $shard_dict id]}
set shard_id [dict get $shard_dict id]

# 2. Verify shard_id is a 40-char string
assert {[string length $shard_id] == 40}

# 3. Verify that for a given node's output, all shard IDs are unique
assert {[dict exists $seen_shard_ids $shard_id] == 0}
dict set seen_shard_ids $shard_id 1
}
}
}
Loading