From ea6c792554308ce6f822c265edfda82fcb324166 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 3 Oct 2024 16:24:37 +0300 Subject: [PATCH 1/3] Fix bug with async pipeline fails with some commands --- redis/asyncio/client.py | 4 ++++ tests/test_asyncio/test_pipeline.py | 13 +++++++++++++ tests/test_pipeline.py | 13 +++++++++++++ 3 files changed, 30 insertions(+) diff --git a/redis/asyncio/client.py b/redis/asyncio/client.py index 039ebfdfae..9508849703 100644 --- a/redis/asyncio/client.py +++ b/redis/asyncio/client.py @@ -1423,6 +1423,10 @@ async def _execute_transaction( # noqa: C901 if not isinstance(r, Exception): args, options = cmd command_name = args[0] + + # Remove keys entry, it needs only for cache. + options.pop("keys", None) + if command_name in self.response_callbacks: r = self.response_callbacks[command_name](r, **options) if inspect.isawaitable(r): diff --git a/tests/test_asyncio/test_pipeline.py b/tests/test_asyncio/test_pipeline.py index 4b29360d72..772ec637d1 100644 --- a/tests/test_asyncio/test_pipeline.py +++ b/tests/test_asyncio/test_pipeline.py @@ -417,3 +417,16 @@ async def test_pipeline_discard(self, r): response = await pipe.execute() assert response[0] assert await r.get("foo") == b"bar" + + @pytest.mark.onlynoncluster + async def test_send_set_commands_over_async_pipeline(self, r: redis.asyncio.Redis): + pipe = r.pipeline() + pipe.hset('hash:1', 'foo', 'bar') + pipe.hset('hash:1', 'bar', 'foo') + pipe.hset('hash:1', 'baz', 'bar') + pipe.hgetall('hash:1') + resp = await pipe.execute() + assert resp == [ + 1, 1, 1, + {b'bar': b'foo', b'baz': b'bar', b'foo': b'bar'} + ] diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 7f10fcad4f..522e790c40 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -412,3 +412,16 @@ def test_pipeline_discard(self, r): response = pipe.execute() assert response[0] assert r.get("foo") == b"bar" + + @pytest.mark.onlynoncluster + def test_send_set_commands_over_pipeline(self, r: redis.Redis): + pipe = r.pipeline() + pipe.hset('hash:1', 'foo', 'bar') + pipe.hset('hash:1', 'bar', 'foo') + pipe.hset('hash:1', 'baz', 'bar') + pipe.hgetall('hash:1') + resp = pipe.execute() + assert resp == [ + 1, 1, 1, + {b'bar': b'foo', b'baz': b'bar', b'foo': b'bar'} + ] From 6d051c0f2b6325b290888f58be8ef9e1a4ea1011 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 3 Oct 2024 16:27:02 +0300 Subject: [PATCH 2/3] Codestyl changes --- tests/test_asyncio/test_pipeline.py | 13 +++++-------- tests/test_pipeline.py | 13 +++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/tests/test_asyncio/test_pipeline.py b/tests/test_asyncio/test_pipeline.py index 772ec637d1..31759d84a3 100644 --- a/tests/test_asyncio/test_pipeline.py +++ b/tests/test_asyncio/test_pipeline.py @@ -421,12 +421,9 @@ async def test_pipeline_discard(self, r): @pytest.mark.onlynoncluster async def test_send_set_commands_over_async_pipeline(self, r: redis.asyncio.Redis): pipe = r.pipeline() - pipe.hset('hash:1', 'foo', 'bar') - pipe.hset('hash:1', 'bar', 'foo') - pipe.hset('hash:1', 'baz', 'bar') - pipe.hgetall('hash:1') + pipe.hset("hash:1", "foo", "bar") + pipe.hset("hash:1", "bar", "foo") + pipe.hset("hash:1", "baz", "bar") + pipe.hgetall("hash:1") resp = await pipe.execute() - assert resp == [ - 1, 1, 1, - {b'bar': b'foo', b'baz': b'bar', b'foo': b'bar'} - ] + assert resp == [1, 1, 1, {b"bar": b"foo", b"baz": b"bar", b"foo": b"bar"}] diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 522e790c40..be7784ad0b 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -416,12 +416,9 @@ def test_pipeline_discard(self, r): @pytest.mark.onlynoncluster def test_send_set_commands_over_pipeline(self, r: redis.Redis): pipe = r.pipeline() - pipe.hset('hash:1', 'foo', 'bar') - pipe.hset('hash:1', 'bar', 'foo') - pipe.hset('hash:1', 'baz', 'bar') - pipe.hgetall('hash:1') + pipe.hset("hash:1", "foo", "bar") + pipe.hset("hash:1", "bar", "foo") + pipe.hset("hash:1", "baz", "bar") + pipe.hgetall("hash:1") resp = pipe.execute() - assert resp == [ - 1, 1, 1, - {b'bar': b'foo', b'baz': b'bar', b'foo': b'bar'} - ] + assert resp == [1, 1, 1, {b"bar": b"foo", b"baz": b"bar", b"foo": b"bar"}] From 6633ee908df166c88e3d491ea769e1fdbebb3423 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 3 Oct 2024 17:07:33 +0300 Subject: [PATCH 3/3] Remove keys option in cluster context --- redis/cluster.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/redis/cluster.py b/redis/cluster.py index fbf5428d40..9dcbad7fc1 100644 --- a/redis/cluster.py +++ b/redis/cluster.py @@ -1163,6 +1163,10 @@ def _execute_command(self, target_node, *args, **kwargs): asking = False connection.send_command(*args, **kwargs) response = redis_node.parse_response(connection, command, **kwargs) + + # Remove keys entry, it needs only for cache. + kwargs.pop("keys", None) + if command in self.cluster_response_callbacks: response = self.cluster_response_callbacks[command]( response, **kwargs