Fix CLUSTER SHARDS command returns empty array (#13422)

Close https://github.com/redis/redis/issues/13414

When the cluster's master node fails and is switched to another node,
the first node in the shard node list (the old master) is no longer
valid.
Add a new method clusterGetMasterFromShard() to obtain the current
master.
This commit is contained in:
debing.sun
2025-01-06 16:03:47 +02:00
committed by YaacovHazan
parent 0e06e67a36
commit f4a6721dfd
2 changed files with 23 additions and 4 deletions
+19 -4
View File
@@ -1722,6 +1722,22 @@ void clusterRemoveNodeFromShard(clusterNode *node) {
sdsfree(s);
}
static clusterNode *clusterGetMasterFromShard(list *nodes) {
clusterNode *n = NULL;
listIter li;
listNode *ln;
listRewind(nodes,&li);
while ((ln = listNext(&li)) != NULL) {
clusterNode *node = listNodeValue(ln);
if (!nodeFailed(node)) {
n = node;
break;
}
}
if (!n) return NULL;
return clusterNodeGetMaster(n);
}
/* -----------------------------------------------------------------------------
* CLUSTER config epoch handling
* -------------------------------------------------------------------------- */
@@ -5727,14 +5743,13 @@ void addNodeDetailsToShardReply(client *c, clusterNode *node) {
/* Add the shard reply of a single shard based off the given primary node. */
void addShardReplyForClusterShards(client *c, list *nodes) {
serverAssert(listLength(nodes) > 0);
clusterNode *n = listNodeValue(listFirst(nodes));
addReplyMapLen(c, 2);
addReplyBulkCString(c, "slots");
/* Use slot_info_pairs from the primary only */
n = clusterNodeGetMaster(n);
if (n->slot_info_pairs != NULL) {
clusterNode *n = clusterGetMasterFromShard(nodes);
if (n && n->slot_info_pairs != NULL) {
serverAssert((n->slot_info_pairs_count % 2) == 0);
addReplyArrayLen(c, n->slot_info_pairs_count);
for (int i = 0; i < n->slot_info_pairs_count; i++)
@@ -124,6 +124,10 @@ test "Verify health as fail for killed node" {
}
}
test "Verify that other nodes can correctly output the new master's slots" {
assert_not_equal {} [dict get [get_node_info_from_shard [R 4 CLUSTER MYID] 8 "shard"] slots]
}
set primary_id 4
set replica_id 0