1414from redis .crc import REDIS_CLUSTER_HASH_SLOTS , key_slot
1515from redis .exceptions import (
1616 AskError ,
17+ AuthenticationError ,
1718 BusyLoadingError ,
1819 ClusterCrossSlotError ,
1920 ClusterDownError ,
@@ -1113,7 +1114,7 @@ def _execute_command(self, target_node, *args, **kwargs):
11131114 )
11141115 return response
11151116
1116- except (RedisClusterException , BusyLoadingError ) as e :
1117+ except (RedisClusterException , BusyLoadingError , AuthenticationError ) as e :
11171118 log .exception (type (e ))
11181119 raise
11191120 except (ConnectionError , TimeoutError ) as e :
@@ -1134,6 +1135,7 @@ def _execute_command(self, target_node, *args, **kwargs):
11341135 else :
11351136 # Hard force of reinitialize of the node/slots setup
11361137 # and try again with the new setup
1138+ target_node .redis_connection = None
11371139 self .nodes_manager .initialize ()
11381140 raise
11391141 except MovedError as e :
@@ -1443,6 +1445,21 @@ def create_redis_node(self, host, port, **kwargs):
14431445 r = Redis (host = host , port = port , ** kwargs )
14441446 return r
14451447
1448+ def _get_or_create_cluster_node (self , host , port , role , tmp_nodes_cache ):
1449+ node_name = get_node_name (host , port )
1450+ # check if we already have this node in the tmp_nodes_cache
1451+ target_node = tmp_nodes_cache .get (node_name )
1452+ if target_node is None :
1453+ # before creating a new cluster node, check if the cluster node already
1454+ # exists in the current nodes cache and has a valid connection so we can
1455+ # reuse it
1456+ target_node = self .nodes_cache .get (node_name )
1457+ if target_node is None or target_node .redis_connection is None :
1458+ # create new cluster node for this cluster
1459+ target_node = ClusterNode (host , port , role )
1460+
1461+ return target_node
1462+
14461463 def initialize (self ):
14471464 """
14481465 Initializes the nodes cache, slots cache and redis connections.
@@ -1521,14 +1538,14 @@ def initialize(self):
15211538
15221539 for slot in cluster_slots :
15231540 primary_node = slot [2 ]
1524- host = primary_node [0 ]
1541+ host = str_if_bytes ( primary_node [0 ])
15251542 if host == "" :
15261543 host = startup_node .host
15271544 port = int (primary_node [1 ])
15281545
1529- target_node = tmp_nodes_cache . get ( get_node_name ( host , port ))
1530- if target_node is None :
1531- target_node = ClusterNode ( host , port , PRIMARY )
1546+ target_node = self . _get_or_create_cluster_node (
1547+ host , port , PRIMARY , tmp_nodes_cache
1548+ )
15321549 # add this node to the nodes cache
15331550 tmp_nodes_cache [target_node .name ] = target_node
15341551
@@ -1539,14 +1556,12 @@ def initialize(self):
15391556 replica_nodes = [slot [j ] for j in range (3 , len (slot ))]
15401557
15411558 for replica_node in replica_nodes :
1542- host = replica_node [0 ]
1559+ host = str_if_bytes ( replica_node [0 ])
15431560 port = replica_node [1 ]
15441561
1545- target_replica_node = tmp_nodes_cache . get (
1546- get_node_name ( host , port )
1562+ target_replica_node = self . _get_or_create_cluster_node (
1563+ host , port , REPLICA , tmp_nodes_cache
15471564 )
1548- if target_replica_node is None :
1549- target_replica_node = ClusterNode (host , port , REPLICA )
15501565 tmp_slots [i ].append (target_replica_node )
15511566 # add this node to the nodes cache
15521567 tmp_nodes_cache [
@@ -1598,7 +1613,7 @@ def initialize(self):
15981613 # Set the default node
15991614 self .default_node = self .get_nodes_by_server_type (PRIMARY )[0 ]
16001615 # Populate the startup nodes with all discovered nodes
1601- self .populate_startup_nodes ( self . nodes_cache . values ())
1616+ self .startup_nodes = tmp_nodes_cache
16021617 # If initialize was called after a MovedError, clear it
16031618 self ._moved_exception = None
16041619
0 commit comments