@@ -2805,8 +2805,10 @@ def raise_error():
2805
2805
2806
2806
m .side_effect = raise_error
2807
2807
2808
- with pytest .raises (Exception , match = "unexpected error" ):
2809
- r .pipeline ().get ("a" ).execute ()
2808
+ with patch .object (Connection , "disconnect" ) as d :
2809
+ with pytest .raises (Exception , match = "unexpected error" ):
2810
+ r .pipeline ().get ("a" ).execute ()
2811
+ assert d .call_count == 1
2810
2812
2811
2813
for cluster_node in r .nodes_manager .nodes_cache .values ():
2812
2814
connection_pool = cluster_node .redis_connection .connection_pool
@@ -3127,7 +3129,7 @@ def raise_ask_error():
3127
3129
assert res == ["MOCK_OK" ]
3128
3130
3129
3131
@pytest .mark .parametrize ("error" , [ConnectionError , TimeoutError ])
3130
- def test_return_previous_acquired_connections (self , r , error ):
3132
+ def test_return_previous_acquired_connections_with_retry (self , r , error ):
3131
3133
# in order to ensure that a pipeline will make use of connections
3132
3134
# from different nodes
3133
3135
assert r .keyslot ("a" ) != r .keyslot ("b" )
@@ -3143,7 +3145,12 @@ def raise_error(target_node, *args, **kwargs):
3143
3145
3144
3146
get_connection .side_effect = raise_error
3145
3147
3146
- r .pipeline ().get ("a" ).get ("b" ).execute ()
3148
+ with patch .object (NodesManager , "initialize" ) as i :
3149
+ i .side_effect = lambda : None # in order to remove disconnect caused by initialize
3150
+
3151
+ with patch .object (Connection , "disconnect" ) as d :
3152
+ r .pipeline ().get ("a" ).get ("b" ).execute ()
3153
+ assert d .call_count == 0
3147
3154
3148
3155
# there should have been two get_connections per execution and
3149
3156
# two executions due to exception raised in the first execution
@@ -3153,6 +3160,39 @@ def raise_error(target_node, *args, **kwargs):
3153
3160
num_of_conns = len (connection_pool ._available_connections )
3154
3161
assert num_of_conns == connection_pool ._created_connections
3155
3162
3163
+ @pytest .mark .parametrize ("error" , [RedisClusterException , BaseException ])
3164
+ def test_return_previous_acquired_connections_without_retry (self , r , error ):
3165
+ # in order to ensure that a pipeline will make use of connections
3166
+ # from different nodes
3167
+ assert r .keyslot ("a" ) != r .keyslot ("b" )
3168
+
3169
+ orig_func = redis .cluster .get_connection
3170
+ with patch ("redis.cluster.get_connection" ) as get_connection :
3171
+
3172
+ def raise_error (target_node , * args , ** kwargs ):
3173
+ if get_connection .call_count == 2 :
3174
+ raise error ("mocked error" )
3175
+ else :
3176
+ return orig_func (target_node , * args , ** kwargs )
3177
+
3178
+ get_connection .side_effect = raise_error
3179
+
3180
+ with patch .object (Connection , "disconnect" ) as d :
3181
+ with pytest .raises (error ):
3182
+ r .pipeline ().get ("a" ).get ("b" ).execute ()
3183
+ assert d .call_count == 0
3184
+
3185
+ # there should have been two get_connections per execution and
3186
+ # two executions due to exception raised in the first execution
3187
+ assert get_connection .call_count == 2
3188
+ for cluster_node in r .nodes_manager .nodes_cache .values ():
3189
+ connection_pool = cluster_node .redis_connection .connection_pool
3190
+ num_of_conns = len (connection_pool ._available_connections )
3191
+ assert num_of_conns == connection_pool ._created_connections
3192
+ # connection must remain connected
3193
+ for conn in connection_pool ._available_connections :
3194
+ assert conn ._sock is not None
3195
+
3156
3196
def test_empty_stack (self , r ):
3157
3197
"""
3158
3198
If pipeline is executed with no commands it should
0 commit comments