Bug: async RedisStorage does not accept `async+unix` URIs
drygdryg opened this issue · 0 comments
drygdryg commented
Async RedisStorage does not accept URIs of the form async+unix
as mentioned in this docstring, like async+unix:///path/to/socket?db=0
.
Program to reproduce
import asyncio
from limits.aio.storage import RedisStorage
from limits.aio.strategies import FixedWindowRateLimiter
from limits import parse
async def main():
storage = RedisStorage('async+unix:///run/redis/redis.sock?db=3')
limiter = FixedWindowRateLimiter(storage)
await limiter.hit(parse('1/minute'), limiter)
asyncio.run(main())
Expected Behaviour
The program should connect to Redis at async+unix:///run/redis/redis.sock?db=3
and run without errors.
Current Behaviour
The program is trying to connect to Redis at 127.0.0.1:6379
, and a connection error occurs:
Traceback (most recent call last):
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/connection.py", line 305, in connect
await self._connect()
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/connection.py", line 792, in _connect
transport, _ = await connection
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/base_events.py", line 1093, in create_connection
raise OSError('Multiple exceptions: {}'.format(
OSError: Multiple exceptions: [Errno 111] Connect call failed ('127.0.0.1', 6379), [Errno 101] Network is unreachable
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/user/limits_bug/reproduce.py", line 14, in <module>
asyncio.run(main())
File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/home/user/limits_bug/reproduce.py", line 11, in main
await limiter.hit(parse('1/minute'), limiter)
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/limits/aio/strategies.py", line 141, in hit
await self.storage.incr(
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/limits/aio/storage/redis.py", line 226, in incr
int, await self.lua_incr_expire.execute([key], [expiry, amount])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/commands/script.py", line 137, in execute
return await self(keys, args, client, readonly)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/commands/script.py", line 117, in __call__
return cast(ResponseType, await method(self.sha, keys=keys, args=args))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/commands/_wrappers.py", line 212, in wrapped
async with command_cache(callable, *args, **kwargs) as response:
File "/usr/lib/python3.11/contextlib.py", line 204, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/commands/_wrappers.py", line 106, in __call__
yield await func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/commands/core.py", line 6117, in evalsha
return await self._evalsha(CommandName.EVALSHA, sha1, keys, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/commands/core.py", line 6098, in _evalsha
return await self.execute_command(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/client/basic.py", line 938, in execute_command
return await self.retry_policy.call_with_retries(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/retry.py", line 76, in call_with_retries
raise last_error
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/retry.py", line 60, in call_with_retries
return await func()
^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/client/basic.py", line 969, in _execute_command
request = await connection.create_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/connection.py", line 620, in create_request
await self.connect()
File "/home/user/limits_bug/venv/lib/python3.11/site-packages/coredis/connection.py", line 311, in connect
raise ConnectionError(str(err)) from err
coredis.exceptions.ConnectionError: Multiple exceptions: [Errno 111] Connect call failed ('127.0.0.1', 6379), [Errno 101] Network is unreachable
My Environment
- limits version: 3.7.0
- Operating system: Arch Linux with Linux kernel v6.6.3
- Redis server v7.2.3 with Unix socket enabled and TCP disabled
Ways to solve this issue
If you specify async+redis+unix
instead of async+unix
in the URI scheme, then everything works correctly. We need to fix the docstring or RedisStorage
logic.