-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Open
Description
Problem
Using redis cluster (async) with redis-py version 7.1.0 results in intermittent NoScript, RedisClusterException or IndexError errors when executing an AsyncScript. These errors are only possible if the cluster client is not initialized on first access (i.e. not created and initialized immediately with await redis.asyncio.RedisCluster.from_url(...)) and there are sufficient concurrent calls to the AsyncScript.
A minimal reproduction:
import asyncio
import random
import redis
async def test_script(client):
script = client.register_script("return KEYS[1]")
random_key = str(random.randint(0, 100))
assert await script([random_key]) == random_key
async def run():
client = redis.asyncio.RedisCluster.from_url(
"redis://localhost:7001", decode_responses=True
)
await client.script_flush()
await client.aclose()
new_client = redis.asyncio.RedisCluster.from_url(
"redis://localhost:7001", decode_responses=True
)
await asyncio.gather(*(test_script(new_client) for _ in range(1024)))
await new_client.aclose()
asyncio.run(run())Noted exceptions:
redis.exceptions.NoScriptError: No matching script. Please use EVAL.
Traceback (most recent call last):
File "/tmp/sandbox/cluster_script.py", line 28, in <module>
asyncio.run(run())
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
return future.result()
File "/tmp/sandbox/cluster_script.py", line 24, in run
await asyncio.gather(*(test_script(new_client) for _ in range(100)))
File "/tmp/sandbox/cluster_script.py", line 10, in test_script
assert await script([random_key]) == random_key
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/commands/core.py", line 6025, in __call__
return await client.evalsha(self.sha, len(keys), *args)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 935, in execute_command
raise e
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 902, in execute_command
ret = await self._execute_command(target_nodes[0], *args, **kwargs)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 964, in _execute_command
return await target_node.execute_command(*args, **kwargs)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 1307, in execute_command
return await self.parse_response(connection, args[0], **kwargs)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 1280, in parse_response
response = await connection.read_response()
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/connection.py", line 635, in read_response
raise response from None
redis.exceptions.NoScriptError: No matching script. Please use EVAL.
IndexError: list index out of range
Traceback (most recent call last):
File "/tmp/sandbox/cluster_script.py", line 28, in <module>
asyncio.run(run())
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
return future.result()
File "/tmp/sandbox/cluster_script.py", line 24, in run
await asyncio.gather(*(test_script(new_client) for _ in range(100)))
File "/tmp/sandbox/cluster_script.py", line 10, in test_script
assert await script([random_key]) == random_key
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/commands/core.py", line 6019, in __call__
return await client.evalsha(self.sha, len(keys), *args)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 935, in execute_command
raise e
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 890, in execute_command
target_nodes = await self._determine_nodes(
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 737, in _determine_nodes
nodes = policy_callback(command)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 444, in <lambda>
self.get_random_primary_or_all_nodes(command_name)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 661, in get_random_primary_or_all_nodes
return self.get_random_primary_node()
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 667, in get_random_primary_node
return random.choice(self.get_primaries())
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/random.py", line 378, in choice
return seq[self._randbelow(len(seq))]
IndexError: list index out of range
redis.exceptions.RedisClusterException: No targets were found to execute ('SCRIPT LOAD', 'return KEYS[1]') command on
Traceback (most recent call last):
File "/tmp/sandbox/cluster_script.py", line 28, in <module>
asyncio.run(run())
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "~/.local/share/uv/python/cpython-3.10.18-macos-x86_64-none/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
return future.result()
File "/tmp/sandbox/cluster_script.py", line 24, in run
await asyncio.gather(*(test_script(new_client) for _ in range(100)))
File "/tmp/sandbox/cluster_script.py", line 10, in test_script
assert await script([random_key]) == random_key
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/commands/core.py", line 6024, in __call__
self.sha = await client.script_load(self.script)
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 935, in execute_command
raise e
File "/tmp/sandbox/.venv/lib/python3.10/site-packages/redis/asyncio/cluster.py", line 896, in execute_command
raise RedisClusterException(
redis.exceptions.RedisClusterException: No targets were found to execute ('SCRIPT LOAD', 'return KEYS[1]') command on
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels