diff --git a/src/cluster_legacy.c b/src/cluster_legacy.c index f14695666..994cc7784 100644 --- a/src/cluster_legacy.c +++ b/src/cluster_legacy.c @@ -2670,7 +2670,7 @@ void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoc * If the sender and myself are in the same shard, try psync. */ clusterSetPrimary(sender, !are_in_same_shard, !are_in_same_shard); clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG | CLUSTER_TODO_UPDATE_STATE | CLUSTER_TODO_FSYNC_CONFIG); - } else if ((sender_slots >= migrated_our_slots) && !are_in_same_shard) { + } else if (nodeIsPrimary(myself) && (sender_slots >= migrated_our_slots) && !are_in_same_shard) { /* When all our slots are lost to the sender and the sender belongs to * a different shard, this is likely due to a client triggered slot * migration. Don't reconfigure this node to migrate to the new shard @@ -6422,11 +6422,12 @@ void clusterCommandSetSlot(client *c) { int slot_was_mine = server.cluster->slots[slot] == my_primary; clusterDelSlot(slot); clusterAddSlot(n, slot); + int shard_is_empty = my_primary->numslots == 0; /* If replica migration is allowed, check if the primary of this shard * loses its last slot and the shard becomes empty. In this case, we * should turn into a replica of the new primary. */ - if (server.cluster_allow_replica_migration && slot_was_mine && my_primary->numslots == 0) { + if (server.cluster_allow_replica_migration && slot_was_mine && shard_is_empty) { serverAssert(n != my_primary); serverLog(LL_NOTICE, "Lost my last slot during slot migration. Reconfiguring myself " @@ -6442,6 +6443,16 @@ void clusterCommandSetSlot(client *c) { clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG | CLUSTER_TODO_UPDATE_STATE | CLUSTER_TODO_FSYNC_CONFIG); } + /* If replica migration is not allowed, check if the primary of this shard + * loses its last slot and the shard becomes empty. In this case, we will + * print the exact same log as during the gossip process. */ + if (!server.cluster_allow_replica_migration && nodeIsPrimary(myself) && slot_was_mine && shard_is_empty) { + serverAssert(n != my_primary); + serverLog(LL_NOTICE, + "My last slot was migrated to node %.40s (%s) in shard %.40s. I am now an empty primary.", + n->name, n->human_nodename, n->shard_id); + } + /* If this node or this node's primary was importing this slot, * assigning the slot to itself also clears the importing status. */ if ((n == myself || n == myself->replicaof) && server.cluster->importing_slots_from[slot]) { diff --git a/tests/unit/cluster/replica-migration.tcl b/tests/unit/cluster/replica-migration.tcl index b40bfcec2..05d652868 100644 --- a/tests/unit/cluster/replica-migration.tcl +++ b/tests/unit/cluster/replica-migration.tcl @@ -372,7 +372,7 @@ proc test_cluster_setslot {type} { fail "valkey-cli --cluster rebalance returns non-zero exit code, output below:\n$result" } - # Wait for R 3 to report that it is an empty replica (cluster-allow-replica-migration no) + # Wait for R 3 to report that it is an empty primary (cluster-allow-replica-migration no) wait_for_log_messages -3 {"*I am now an empty primary*"} 0 1000 50 if {$type == "setslot"} {