Skip to content

Commit 69987bd

Browse files
committed
[GROW-3134] release already acquired connections, when get_connections raised an exception (#3)
* [GROW-3134] release already acquired connections, when get_connections raised an exception * fix style (cherry picked from commit 94bb915)
1 parent cabb246 commit 69987bd

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

redis/cluster.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,8 @@ def _send_cluster_commands(
19951995
try:
19961996
connection = get_connection(redis_node, c.args)
19971997
except (ConnectionError, TimeoutError) as e:
1998+
for n in nodes.values():
1999+
n.connection_pool.release(n.connection)
19982000
if self.retry and isinstance(e, self.retry._supported_errors):
19992001
backoff = self.retry._backoff.compute(attempts_count)
20002002
if backoff > 0:

tests/test_cluster.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import pytest
1010

11+
import redis.cluster
1112
from redis import Redis
1213
from redis.backoff import (
1314
ConstantBackoff,
@@ -2925,6 +2926,33 @@ def raise_ask_error():
29252926
assert ask_node.redis_connection.connection.read_response.called
29262927
assert res == ["MOCK_OK"]
29272928

2929+
@pytest.mark.parametrize("error", [ConnectionError, TimeoutError])
2930+
def test_return_previous_acquired_connections(self, r, error):
2931+
# in order to ensure that a pipeline will make use of connections
2932+
# from different nodes
2933+
assert r.keyslot("a") != r.keyslot("b")
2934+
2935+
orig_func = redis.cluster.get_connection
2936+
with patch("redis.cluster.get_connection") as get_connection:
2937+
2938+
def raise_error(target_node, *args, **kwargs):
2939+
if get_connection.call_count == 2:
2940+
raise error("mocked error")
2941+
else:
2942+
return orig_func(target_node, *args, **kwargs)
2943+
2944+
get_connection.side_effect = raise_error
2945+
2946+
r.pipeline().get("a").get("b").execute()
2947+
2948+
# there should have been two get_connections per execution and
2949+
# two executions due to exception raised in the first execution
2950+
assert get_connection.call_count == 4
2951+
for cluster_node in r.nodes_manager.nodes_cache.values():
2952+
connection_pool = cluster_node.redis_connection.connection_pool
2953+
num_of_conns = len(connection_pool._available_connections)
2954+
assert num_of_conns == connection_pool._created_connections
2955+
29282956
def test_empty_stack(self, r):
29292957
"""
29302958
If pipeline is executed with no commands it should

0 commit comments

Comments
 (0)