@@ -2681,8 +2681,10 @@ def raise_error():
2681
2681
2682
2682
m .side_effect = raise_error
2683
2683
2684
- with pytest .raises (Exception , match = "unexpected error" ):
2685
- r .pipeline ().get ("a" ).execute ()
2684
+ with patch .object (Connection , "disconnect" ) as d :
2685
+ with pytest .raises (Exception , match = "unexpected error" ):
2686
+ r .pipeline ().get ("a" ).execute ()
2687
+ assert d .call_count == 1
2686
2688
2687
2689
for cluster_node in r .nodes_manager .nodes_cache .values ():
2688
2690
connection_pool = cluster_node .redis_connection .connection_pool
@@ -2984,7 +2986,7 @@ def raise_ask_error():
2984
2986
assert res == ["MOCK_OK" ]
2985
2987
2986
2988
@pytest .mark .parametrize ("error" , [ConnectionError , TimeoutError ])
2987
- def test_return_previous_acquired_connections (self , r , error ):
2989
+ def test_return_previous_acquired_connections_with_retry (self , r , error ):
2988
2990
# in order to ensure that a pipeline will make use of connections
2989
2991
# from different nodes
2990
2992
assert r .keyslot ("a" ) != r .keyslot ("b" )
@@ -3000,7 +3002,13 @@ def raise_error(target_node, *args, **kwargs):
3000
3002
3001
3003
get_connection .side_effect = raise_error
3002
3004
3003
- r .pipeline ().get ("a" ).get ("b" ).execute ()
3005
+ with patch .object (NodesManager , "initialize" ) as i :
3006
+ # in order to remove disconnect caused by initialize
3007
+ i .side_effect = lambda : None
3008
+
3009
+ with patch .object (Connection , "disconnect" ) as d :
3010
+ r .pipeline ().get ("a" ).get ("b" ).execute ()
3011
+ assert d .call_count == 0
3004
3012
3005
3013
# there should have been two get_connections per execution and
3006
3014
# two executions due to exception raised in the first execution
@@ -3010,6 +3018,39 @@ def raise_error(target_node, *args, **kwargs):
3010
3018
num_of_conns = len (connection_pool ._available_connections )
3011
3019
assert num_of_conns == connection_pool ._created_connections
3012
3020
3021
+ @pytest .mark .parametrize ("error" , [RedisClusterException , BaseException ])
3022
+ def test_return_previous_acquired_connections_without_retry (self , r , error ):
3023
+ # in order to ensure that a pipeline will make use of connections
3024
+ # from different nodes
3025
+ assert r .keyslot ("a" ) != r .keyslot ("b" )
3026
+
3027
+ orig_func = redis .cluster .get_connection
3028
+ with patch ("redis.cluster.get_connection" ) as get_connection :
3029
+
3030
+ def raise_error (target_node , * args , ** kwargs ):
3031
+ if get_connection .call_count == 2 :
3032
+ raise error ("mocked error" )
3033
+ else :
3034
+ return orig_func (target_node , * args , ** kwargs )
3035
+
3036
+ get_connection .side_effect = raise_error
3037
+
3038
+ with patch .object (Connection , "disconnect" ) as d :
3039
+ with pytest .raises (error ):
3040
+ r .pipeline ().get ("a" ).get ("b" ).execute ()
3041
+ assert d .call_count == 0
3042
+
3043
+ # there should have been two get_connections per execution and
3044
+ # two executions due to exception raised in the first execution
3045
+ assert get_connection .call_count == 2
3046
+ for cluster_node in r .nodes_manager .nodes_cache .values ():
3047
+ connection_pool = cluster_node .redis_connection .connection_pool
3048
+ num_of_conns = len (connection_pool ._available_connections )
3049
+ assert num_of_conns == connection_pool ._created_connections
3050
+ # connection must remain connected
3051
+ for conn in connection_pool ._available_connections :
3052
+ assert conn ._sock is not None
3053
+
3013
3054
def test_empty_stack (self , r ):
3014
3055
"""
3015
3056
If pipeline is executed with no commands it should
0 commit comments