Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: RedisBackend key naming #8

Closed
euri10 opened this issue Feb 7, 2022 · 3 comments · Fixed by #9
Closed

Feature: RedisBackend key naming #8

euri10 opened this issue Feb 7, 2022 · 3 comments · Fixed by #9

Comments

@euri10
Copy link
Collaborator

euri10 commented Feb 7, 2022

greetings, I'm starting playing a little with this nicely laid package to get a sense if I could use it in subsequent developments.

I wanted to know if you'd accept a PR that would let the user prefix his redis key whose name is currently by default the result of generate_id by a prefix of some sort, or maybe a callable that would return a more intuitive redis key.

The motivation is to try to keep the db organized, having keys like session:xxxx instead of xxxx is a little bit more easy on the potential searches, analyses that could come down the road.

so far I just implemented a very rough custom backend that let me pass a redis_key arg:

  1. if that arg is a string, the redis key will be key_prefix:session_id
  2. if that arg is a callable, it return the string the callable generates with the session_id argument

Just posing my thoughts here and my current rough implementation hopefully to see if that could be incorporated in the package, if not no worries :)

import inspect
import typing

import aioredis
from starsessions import (
    ImproperlyConfigured,
    JsonSerializer,
    Serializer,
    SessionBackend,
)


class MyRedisBackend(SessionBackend):
    """Stores session data in a Redis server."""

    def __init__(
        self,
        url: str = None,
        connection: aioredis.Redis = None,
        serializer: Serializer = None,
        redis_key: typing.Union[str, typing.Callable[[str], str]] = None,
    ) -> None:
        assert (  # noqa: S101
            url or connection
        ), 'Either "url" or "connection" arguments must be provided.'
        self._serializer = serializer or JsonSerializer()
        self._connection = connection or aioredis.from_url(url)
        if callable(redis_key):
            if "session_id" not in inspect.signature(redis_key).parameters.keys():
                raise ImproperlyConfigured(
                    "Your callable redis_key needs to have a session_id parameter"
                )
        self.redis_key = redis_key

    def get_redis_key(self, session_id: str) -> str:
        if isinstance(self.redis_key, str):
            return f"{self.redis_key}:{session_id}"
        elif callable(self.redis_key):
            return self.redis_key(session_id)
        else:
            return session_id

    async def read(self, session_id: str) -> typing.Dict:
        value = await self._connection.get(self.get_redis_key(session_id))
        if value is None:
            return {}
        return self._serializer.deserialize(value)

    async def write(
        self, data: typing.Dict, session_id: typing.Optional[str] = None
    ) -> str:
        session_id = session_id or await self.generate_id()
        await self._connection.set(
            self.get_redis_key(session_id), self._serializer.serialize(data)
        )
        return session_id

    async def remove(self, session_id: str) -> None:
        await self._connection.delete(self.get_redis_key(session_id))

    async def exists(self, session_id: str) -> bool:
        result = await self._connection.exists(self.get_redis_key(session_id))
        return result > 0

@alex-oleshkevich
Copy link
Owner

Sure, that's a nice addon!
A small notice: I think we have to allow either a callback or a prefix string. Having both seems too complicated at this moment.

@euri10
Copy link
Collaborator Author

euri10 commented Feb 7, 2022

Sure, that's a nice addon! A small notice: I think we have to allow either a callback or a prefix string. Having both seems too complicated at this moment.

ok then I'll push a PR for a callable later today, seems to me that it gives the end-user the best flexibility in naming his redis key

@euri10
Copy link
Collaborator Author

euri10 commented Feb 8, 2022

thanks for the quick push @alex-oleshkevich !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants