youknowone/ring

Guidance on how to avoid repetition

striveforbest opened this issue · 4 comments

More of a guidance request rather than an issue but hoping you can help. I am using a setup like this:

import ring
from django_redis import get_redis_connection


redis_connection = get_redis_connection('default')


class InteractionOverview:
    def __init__(self, organization: Organization, end_date: date) -> None:
        self.organization = organization
        self.end_date = end_date

    def __ring_key__(self) -> str:
        return f'{self.organization}({self.organization.id}):{self.end_date}'

    @ring.redis(redis_connection, coder='pickle')
    def item_interaction_trends(self, start_date: date = None, end_date: date = None) -> dict:```
        pass


    @ring.redis(redis_connection, coder='pickle')
    def product_interaction_trends(self, start_date: date = None, end_date: date = None) -> dict:```
        pass

etc...

I do not love the repetition of @ring.redis(redis_connection, coder='pickle') above each method, additionally, i'd prefer to abstract it out from the end engineer writing similar code. Hence I thought maybe i'd create a custom decorator that ultimately decorates with @ring.redis(redis_connection, coder='pickle'). The desired syntax is something like:

    @my_redis_cache
    def item_interaction_trends(self, start_date: date = None, end_date: date = None) -> dict:```
        pass

where my custom my_redis_cache decorator would be responsible for decorating the item_interaction_trends with @ring.redis(redis_connection, coder='pickle')

Any guidance helps.

I think this must work. I ususally used in this way.

my_redis_cache = ring.redis(redis_connection, coder='pickle')

@my_redis_cache
def item_interaction_trends(self, start_date: date = None, end_date: date = None) -> dict:
    pass

Please let me know if you meet any problem to do this.

@youknowone
this will do for sure. it's more of an issue if I want some additional custom logic to happen within my override. the standard decorating a decorator approach doesn't seem to work for me, I think because your decorator works on classmethods and optionally receives self/cls as a parm?

Could you show me a specific scenario with an example? Ring decorator is designed to be used to top of the other decorators. But I am not sure if it can be a problem in some situations.

I don't have an example as of right now. but I was thinking to abstract out connection and coder away (which your proposed solution solves) but also add something to schedule an async job to warm up the cache. but if you could show me a way to even have a print statement that'd do.