Skip to content

Commit

Permalink
Merge pull request #18 from SebastiaanZ/aioredis-v2
Browse files Browse the repository at this point in the history
Migrate To aioredis v2
  • Loading branch information
HassanAbouelela committed Jul 19, 2022
2 parents 6a68850 + c9b40dd commit 3c476f7
Show file tree
Hide file tree
Showing 12 changed files with 505 additions and 505 deletions.
4 changes: 2 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ coveralls = "~=2.2.0"
time-machine = "~=1.3.0"

[packages]
aioredis = "~=1.3.1"
"fakeredis[lua]" = "~=1.4.4"
aioredis = "~=2.0"
"fakeredis[lua]" = "~=1.7.1"

[requires]
python_version = "3.8"
Expand Down
453 changes: 280 additions & 173 deletions Pipfile.lock

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,22 @@ pip install async-rediscache[fakeredis]
## Basic use

### Creating a `RedisSession`
To use a `RedisCache`, you first have to create a `RedisSession` instance that manages the connection pool to Redis. You can create the `RedisSession` at any point but make sure to call the `connect` method from an asynchronous context (see [this explanation](https://docs.aiohttp.org/en/stable/faq.html#why-is-creating-a-clientsession-outside-of-an-event-loop-dangerous) for why).
To use a `RedisCache`, you first have to create a `RedisSession` instance that manages the connection to Redis. You can create the `RedisSession` at any point but make sure to call the `connect` method from an asynchronous context (see [this explanation](https://docs.aiohttp.org/en/stable/faq.html#why-is-creating-a-clientsession-outside-of-an-event-loop-dangerous) for why).

```python
import async_rediscache

async def main():
session = async_rediscache.RedisSession()
session = async_rediscache.RedisSession("redis://localhost")
await session.connect()

# Do something interesting

await session.close()
```

### Creating a `RedisSession` with a network connection

```python
import async_rediscache
async def main():
connection = {"address": "redis://127.0.0.1:6379"}
async_rediscache.RedisSession(**connection)
Expand Down Expand Up @@ -84,7 +83,7 @@ Here are some usage examples:
import async_rediscache

async def main():
session = async_rediscache.RedisSession()
session = async_rediscache.RedisSession("redis://localhost")
await session.connect()

cache = async_rediscache.RedisCache(namespace="python")
Expand All @@ -110,8 +109,6 @@ async def main():
await cache.delete("Barry")
await cache.increment("Brett", 1) # Increment Brett's int by 1
await cache.clear()

await session.close()
```

#### `RedisQueue`
Expand Down
68 changes: 34 additions & 34 deletions async_rediscache/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import aioredis

__all__ = ['RedisSession', 'RedisSessionClosed', 'RedisSessionNotInitialized']
__all__ = ['RedisSession', 'RedisSessionNotInitialized', 'RedisSessionNotConnected']

log = logging.getLogger(__name__)

Expand All @@ -13,8 +13,8 @@ class RedisSessionNotInitialized(RuntimeError):
"""Raised when the RedisSession instance has not been initialized yet."""


class RedisSessionClosed(RuntimeError):
"""Exception raised when something attempts operations on a closed redis session."""
class RedisSessionNotConnected(RuntimeError):
"""Raised when trying to access the Redis client before a connection has been created."""


class FakeRedisNotInstalled(ImportError):
Expand Down Expand Up @@ -55,22 +55,26 @@ class RedisSession(metaclass=RedisSingleton):
creates it, run the loop until the `connect` coroutine is completed, and
passing the loop to `discord.ext.commands.Bot.__init__` afterwards.
The `url` argument, and kwargs are passed directly to the `aioredis.from_url` method.
Example:
redis_session = RedisSession()
redis_session = RedisSession("redis://localhost")
loop = asyncio.get_event_loop()
loop.run_until_complete(redis_session.connect(...))
loop.run_until_complete(redis_session.connect())
bot = discord.ext.commands.Bot(..., loop=loop)
"""

_instance: RedisSession = None

def __init__(
self, *, global_namespace: str = "", use_fakeredis: bool = False, **session_kwargs
self, url: str, *, global_namespace: str = "", use_fakeredis: bool = False, **session_kwargs
) -> None:
self.global_namespace = global_namespace
self._pool = None
self.url = url
self._client = None
self._session_kwargs = session_kwargs
self._use_fakeredis = use_fakeredis
self.connected = False

@classmethod
def get_current_session(cls) -> RedisSession:
Expand All @@ -86,28 +90,22 @@ def get_current_session(cls) -> RedisSession:
return cls._instance

@property
def pool(self) -> aioredis.Redis:
def client(self) -> aioredis.Redis:
"""
Get the connection pool after checking if it is still connected.
Get the redis client object to perform commands on.
This property will raise a `RedisSessionClosed` if it's accessed after
the pool has been closed.
This property will raise a `RedisSessionNotConnected` if it is accessed
before the connect method is called.
"""
if self._pool.closed:
raise RedisSessionClosed(
"attempting to access connections pool after it has been closed."
if not self.connected:
raise RedisSessionNotConnected(
"attempting to access the client before the connection has been created."
)

return self._pool

@property
def closed(self) -> bool:
"""Return whether or not the RedisSession is closed."""
return self._pool is None or self._pool.closed
return self._client

async def connect(self) -> None:
"""Connect to Redis by creating the connections pool."""
log.debug("Creating Redis connections pool.")
"""Connect to Redis by instantiating the redis instance."""
log.debug("Creating Redis client.")

# Decide if we want to use `fakeredis` or an actual Redis server. The
# option to use `fakeredis.aioredis` is provided to aid with running the
Expand All @@ -126,18 +124,20 @@ async def connect(self) -> None:
)

kwargs = dict(self._session_kwargs)
# Match the behavior of `aioredis.from_url` by updating the kwargs using the URL
url_options = aioredis.connection.parse_url(self.url)
kwargs.update(dict(url_options))

# the `address` and `password` kwargs are not supported by redis
kwargs.pop("address", None)
kwargs.pop("password", None)
# The following kwargs are not supported by fakeredis
[kwargs.pop(kwarg, None) for kwarg in (
"address", "username", "password", "port", "timeout"
)]

pool_constructor = fakeredis.aioredis.create_redis_pool(**kwargs)
self._client = fakeredis.aioredis.FakeRedis(**kwargs)
else:
pool_constructor = aioredis.create_redis_pool(**self._session_kwargs)

self._pool = await pool_constructor
self._client = aioredis.from_url(self.url, **self._session_kwargs)

async def close(self) -> None:
"""Close the pool and wait for pending operations to be processed."""
self._pool.close()
await self._pool.wait_closed()
# The connection pool client does not expose any way to connect to the server, so
# we try to perform a request to confirm the connection
await self._client.ping()
self.connected = True
Loading

0 comments on commit 3c476f7

Please sign in to comment.