diff options
author | Bar Shaul <88437685+barshaul@users.noreply.github.com> | 2022-11-10 13:16:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-10 13:16:49 +0200 |
commit | 67214cc3eaa7890c87e45550b8320779f954094b (patch) | |
tree | 3bca8b8913224255bdf72de79265ca0441cecb1c /tests/test_asyncio/test_cluster.py | |
parent | bb06ccd52924800ac501d17c8a42038c8e5c5770 (diff) | |
download | redis-py-67214cc3eaa7890c87e45550b8320779f954094b.tar.gz |
Failover handling improvements for RedisCluster and Async RedisCluster (#2377)
* Cluster&AsyncCluster: Removed handling of timeouts/connection errors within the cluster loop, fixed "cannot pickle '_thread.lock' object" bug, added client's side failover handling improvements
* Fixed linters
* Type fixes
* Added to CHANGES
* Added getter and setter for the client's retry object and added more tests
* Fixed linters
* Fixed test
* Fixed test_client_kill test
* Changed get_default_backoff to default_backoff, removed retry_on_error and connection_error_retry_attempts from RedisCluster, default retry changed to no retries
* Fixing linters
* Reverting deletion of connection_error_retry_attempts to maintain backward compatibility
* Updating retry object for existing and new connections
* Changed the default value of reinitialize_steps from 10 to 5
* fix review comments
Co-authored-by: Chayim <chayim@users.noreply.github.com>
Co-authored-by: dvora-h <dvora.heller@redis.com>
Co-authored-by: dvora-h <67596500+dvora-h@users.noreply.github.com>
Diffstat (limited to 'tests/test_asyncio/test_cluster.py')
-rw-r--r-- | tests/test_asyncio/test_cluster.py | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/tests/test_asyncio/test_cluster.py b/tests/test_asyncio/test_cluster.py index 27f1190..38bcaf6 100644 --- a/tests/test_asyncio/test_cluster.py +++ b/tests/test_asyncio/test_cluster.py @@ -13,6 +13,8 @@ from _pytest.fixtures import FixtureRequest from redis.asyncio.cluster import ClusterNode, NodesManager, RedisCluster from redis.asyncio.connection import Connection, SSLConnection from redis.asyncio.parser import CommandsParser +from redis.asyncio.retry import Retry +from redis.backoff import ExponentialBackoff, NoBackoff, default_backoff from redis.cluster import PIPELINE_BLOCKED_COMMANDS, PRIMARY, REPLICA, get_node_name from redis.crc import REDIS_CLUSTER_HASH_SLOTS, key_slot from redis.exceptions import ( @@ -247,6 +249,76 @@ class TestRedisClusterObj: ] ) + async def test_cluster_set_get_retry_object(self, request: FixtureRequest): + retry = Retry(NoBackoff(), 2) + url = request.config.getoption("--redis-url") + async with RedisCluster.from_url(url, retry=retry) as r: + assert r.get_retry()._retries == retry._retries + assert isinstance(r.get_retry()._backoff, NoBackoff) + for node in r.get_nodes(): + n_retry = node.connection_kwargs.get("retry") + assert n_retry is not None + assert n_retry._retries == retry._retries + assert isinstance(n_retry._backoff, NoBackoff) + rand_cluster_node = r.get_random_node() + existing_conn = rand_cluster_node.acquire_connection() + # Change retry policy + new_retry = Retry(ExponentialBackoff(), 3) + r.set_retry(new_retry) + assert r.get_retry()._retries == new_retry._retries + assert isinstance(r.get_retry()._backoff, ExponentialBackoff) + for node in r.get_nodes(): + n_retry = node.connection_kwargs.get("retry") + assert n_retry is not None + assert n_retry._retries == new_retry._retries + assert isinstance(n_retry._backoff, ExponentialBackoff) + assert existing_conn.retry._retries == new_retry._retries + new_conn = rand_cluster_node.acquire_connection() + assert new_conn.retry._retries == new_retry._retries + + async def test_cluster_retry_object(self, request: FixtureRequest) -> None: + url = request.config.getoption("--redis-url") + async with RedisCluster.from_url(url) as rc_default: + # Test default retry + retry = rc_default.connection_kwargs.get("retry") + assert isinstance(retry, Retry) + assert retry._retries == 3 + assert isinstance(retry._backoff, type(default_backoff())) + assert rc_default.get_node("127.0.0.1", 16379).connection_kwargs.get( + "retry" + ) == rc_default.get_node("127.0.0.1", 16380).connection_kwargs.get("retry") + + retry = Retry(ExponentialBackoff(10, 5), 5) + async with RedisCluster.from_url(url, retry=retry) as rc_custom_retry: + # Test custom retry + assert ( + rc_custom_retry.get_node("127.0.0.1", 16379).connection_kwargs.get( + "retry" + ) + == retry + ) + + async with RedisCluster.from_url( + url, connection_error_retry_attempts=0 + ) as rc_no_retries: + # Test no connection retries + assert ( + rc_no_retries.get_node("127.0.0.1", 16379).connection_kwargs.get( + "retry" + ) + is None + ) + + async with RedisCluster.from_url( + url, retry=Retry(NoBackoff(), 0) + ) as rc_no_retries: + assert ( + rc_no_retries.get_node("127.0.0.1", 16379) + .connection_kwargs.get("retry") + ._retries + == 0 + ) + async def test_empty_startup_nodes(self) -> None: """ Test that exception is raised when empty providing empty startup_nodes @@ -1289,8 +1361,11 @@ class TestClusterRedisCommands: assert "addr" in info @skip_if_server_version_lt("2.6.9") - async def test_client_kill(self, r: RedisCluster, r2: RedisCluster) -> None: + async def test_client_kill( + self, r: RedisCluster, create_redis: Callable[..., RedisCluster] + ) -> None: node = r.get_primaries()[0] + r2 = await create_redis(cls=RedisCluster, flushdb=False) await r.client_setname("redis-py-c1", target_nodes="all") await r2.client_setname("redis-py-c2", target_nodes="all") clients = [ @@ -1311,6 +1386,7 @@ class TestClusterRedisCommands: ] assert len(clients) == 1 assert clients[0].get("name") == "redis-py-c1" + await r2.close() @skip_if_server_version_lt("2.6.0") async def test_cluster_bitop_not_empty_string(self, r: RedisCluster) -> None: |