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

Can't access ring-specific attributes on a cached property #180

Open
striveforbest opened this issue Jul 17, 2021 · 3 comments
Open

Can't access ring-specific attributes on a cached property #180

striveforbest opened this issue Jul 17, 2021 · 3 comments

Comments

@striveforbest
Copy link

I am writing a reports/calculations module and using ring to store the results of expensive calculations in redis.
I started with using classmethods and it worked as expected, I was able to access ring-specific attributes (has, key, etc) but with property I cannot seem to be able to.

Here is a simplified example:

from django_redis import get_redis_connection


redis_connection = get_redis_connection('default')


class ProductCalculations:
    """
    Generate business intelligence from an organizations Product data.
    """

    def __init__(self, organization):
        self.organization = organization

    def __ring_key__(self):
        """ Required for setting a correct cache key. """
        return self.organization

    @ring.redis(redis_connection, coder='pickle')
    @property
    def products(self) -> 'QuerySet[Product]':
        return Product.objects.filter(organization=self.organization)

    @ring.redis(redis_connection, coder='pickle')
    @property
    def product_count(self) -> int:
        return self.products.count()

Upon inspecting the results, I can't seem to be able to access ring-specific attributes:

org = Organization.objects.all()[0]

calc = ProductCalculations(org)
calc.products

calc.products.has(o)

AttributeError: 'QuerySet' object has no attribute 'has'

Is this an expected behavior? How can I access ring-specific attributes on the cached property?

@youknowone
Copy link
Owner

Yes, it is an expected behavior. We need Ring object to access to the ring attributes, but property returns the result of function instead of ring object.

Not very neat, but I sometimes used this kind of workaround for development:

class ProductCalculations:
    @ring.redis(redis_connection, coder='pickle')
    def _products(self) -> 'QuerySet[Product]':
        return Product.objects.filter(organization=self.organization)

    @property
    def products(self):
        return self._products()

There is no way to access there for now.
Maybe we need a tool like, ring.obtain(ProductCalculations, calc, 'products')

@striveforbest
Copy link
Author

That's what I suspected. Thanks for the proposed workaround @youknowone . Something like obtain_ring function would be really handy. Hoping to see it in the future.

@striveforbest
Copy link
Author

@youknowone so if it's a property and I don't have access to ring methods, how do I force the recache? I do need access to .update() and, potentially, .delete(). Sometimes I know the code/logic changed and I need to recache otherwise i'd be getting stale results. But Ring just returns stored/stale results because the key exists.

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

No branches or pull requests

2 participants