diff --git a/redis/cluster.py b/redis/cluster.py index f1150073a9..235d8f2dc3 100644 --- a/redis/cluster.py +++ b/redis/cluster.py @@ -1437,6 +1437,8 @@ def _get_or_create_cluster_node(self, host, port, role, tmp_nodes_cache): if target_node is None or target_node.redis_connection is None: # create new cluster node for this cluster target_node = ClusterNode(host, port, role) + if target_node.server_type != role: + target_node.server_type = role return target_node diff --git a/tests/test_cluster.py b/tests/test_cluster.py index 27cfee1c6f..55b660c7c5 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -2262,6 +2262,57 @@ def test_init_slots_cache(self): assert len(n_manager.nodes_cache) == 6 + def test_init_promote_server_type_for_node_in_cache(self): + """ + When replica is promoted to master, nodes_cache must change the server type + accordingly + """ + cluster_slots_before_promotion = [ + [0, 16383, ["127.0.0.1", 7000], ["127.0.0.1", 7003]] + ] + cluster_slots_after_promotion = [ + [0, 16383, ["127.0.0.1", 7003], ["127.0.0.1", 7004]] + ] + + cluster_slots_results = [ + cluster_slots_before_promotion, + cluster_slots_after_promotion, + ] + + with patch.object(Redis, "execute_command") as execute_command_mock: + + def execute_command(*_args, **_kwargs): + if _args[0] == "CLUSTER SLOTS": + mock_cluster_slots = cluster_slots_results.pop(0) + return mock_cluster_slots + elif _args[0] == "COMMAND": + return {"get": [], "set": []} + elif _args[0] == "INFO": + return {"cluster_enabled": True} + elif len(_args) > 1 and _args[1] == "cluster-require-full-coverage": + return {"cluster-require-full-coverage": False} + else: + return execute_command_mock(*_args, **_kwargs) + + execute_command_mock.side_effect = execute_command + + nm = NodesManager( + startup_nodes=[ClusterNode(host=default_host, port=default_port)], + from_url=False, + require_full_coverage=False, + dynamic_startup_nodes=True, + ) + + assert nm.default_node.host == "127.0.0.1" + assert nm.default_node.port == 7000 + assert nm.default_node.server_type == PRIMARY + + nm.initialize() + + assert nm.default_node.host == "127.0.0.1" + assert nm.default_node.port == 7003 + assert nm.default_node.server_type == PRIMARY + def test_init_slots_cache_cluster_mode_disabled(self): """ Test that creating a RedisCluster failes if one of the startup nodes