14
14
from redis .crc import REDIS_CLUSTER_HASH_SLOTS , key_slot
15
15
from redis .exceptions import (
16
16
AskError ,
17
+ AuthenticationError ,
17
18
BusyLoadingError ,
18
19
ClusterCrossSlotError ,
19
20
ClusterDownError ,
@@ -1113,7 +1114,7 @@ def _execute_command(self, target_node, *args, **kwargs):
1113
1114
)
1114
1115
return response
1115
1116
1116
- except (RedisClusterException , BusyLoadingError ) as e :
1117
+ except (RedisClusterException , BusyLoadingError , AuthenticationError ) as e :
1117
1118
log .exception (type (e ))
1118
1119
raise
1119
1120
except (ConnectionError , TimeoutError ) as e :
@@ -1134,6 +1135,7 @@ def _execute_command(self, target_node, *args, **kwargs):
1134
1135
else :
1135
1136
# Hard force of reinitialize of the node/slots setup
1136
1137
# and try again with the new setup
1138
+ target_node .redis_connection = None
1137
1139
self .nodes_manager .initialize ()
1138
1140
raise
1139
1141
except MovedError as e :
@@ -1443,6 +1445,21 @@ def create_redis_node(self, host, port, **kwargs):
1443
1445
r = Redis (host = host , port = port , ** kwargs )
1444
1446
return r
1445
1447
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
+
1446
1463
def initialize (self ):
1447
1464
"""
1448
1465
Initializes the nodes cache, slots cache and redis connections.
@@ -1521,14 +1538,14 @@ def initialize(self):
1521
1538
1522
1539
for slot in cluster_slots :
1523
1540
primary_node = slot [2 ]
1524
- host = primary_node [0 ]
1541
+ host = str_if_bytes ( primary_node [0 ])
1525
1542
if host == "" :
1526
1543
host = startup_node .host
1527
1544
port = int (primary_node [1 ])
1528
1545
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
+ )
1532
1549
# add this node to the nodes cache
1533
1550
tmp_nodes_cache [target_node .name ] = target_node
1534
1551
@@ -1539,14 +1556,12 @@ def initialize(self):
1539
1556
replica_nodes = [slot [j ] for j in range (3 , len (slot ))]
1540
1557
1541
1558
for replica_node in replica_nodes :
1542
- host = replica_node [0 ]
1559
+ host = str_if_bytes ( replica_node [0 ])
1543
1560
port = replica_node [1 ]
1544
1561
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
1547
1564
)
1548
- if target_replica_node is None :
1549
- target_replica_node = ClusterNode (host , port , REPLICA )
1550
1565
tmp_slots [i ].append (target_replica_node )
1551
1566
# add this node to the nodes cache
1552
1567
tmp_nodes_cache [
@@ -1598,7 +1613,7 @@ def initialize(self):
1598
1613
# Set the default node
1599
1614
self .default_node = self .get_nodes_by_server_type (PRIMARY )[0 ]
1600
1615
# Populate the startup nodes with all discovered nodes
1601
- self .populate_startup_nodes ( self . nodes_cache . values ())
1616
+ self .startup_nodes = tmp_nodes_cache
1602
1617
# If initialize was called after a MovedError, clear it
1603
1618
self ._moved_exception = None
1604
1619
0 commit comments