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

Allow multiple keys for cache_on_save #212

Open
chemary opened this issue Oct 5, 2016 · 6 comments
Open

Allow multiple keys for cache_on_save #212

chemary opened this issue Oct 5, 2016 · 6 comments

Comments

@chemary
Copy link

chemary commented Oct 5, 2016

I use django-cacheops for managing MySQL replication lag, so I set cache_on_save to avoid fast reads after write to get stale data, I think it will be handy to be able to specify multiple keys.

An example:
I usually get User model by id or by username so both queries are cached pointing to the same object:

"conj:ftmanager_user:username=5feb24948664d6be7e36aed63e453e0cdc9be81d"
"conj:ftmanager_user:id=108547"

If I set cache_on_save to one of them for instance username, when User is modified the other cache is deleted so next User.objects.get(id=108547) will hit the database.

My suggested implementation:

class ManagerMixin(object):
    ...
    def _post_save(self, sender, instance, **kwargs):
            ...
            keys = ['pk'] if cache_on_save is True else cache_on_save
            for key in keys:
                cond = {key: getattr(instance, key)}
                qs = sender.objects.inplace().filter(**cond).order_by()
                if MAX_GET_RESULTS:
                    qs = qs[:MAX_GET_RESULTS + 1]
                qs._cache_results(qs._cache_key(), [instance])
@Suor
Copy link
Owner

Suor commented Oct 7, 2016

Are you willing to make a pull request?

@chemary
Copy link
Author

chemary commented Oct 7, 2016

I have not made the pull request because I don't know if other find there is a need for this feature or if the solution is correct.

I have noticed for instance that having two keys, stores the same object two times in Redis

"conj:ftmanager_user:username=5feb24948664d6be7e36aed63e453e0cdc9be81d"
"conj:ftmanager_user:id=108547"

point to two objects that contains the same data, they should point to the same result?

q:9be3411703144230d7baae7c1d84cb8d
q:47d86696fdab13139c2bd19c77bcf22b

@Suor
Copy link
Owner

Suor commented Oct 7, 2016

Key is determined by queryset, there is no way to know that 2 different querysets result in same thing until you execute them. So, yes, same object is stored twice under 2 different keys. This is normal behavior and your implementation is correct regarding this issue. You should, however, handle cache_on_save=<string> case.

The idea of somehow compressing it, e.g. using content addressed values in cache with queryset keys refering to single stored object is interesting, but probably won't be worth the hustle.

@Suor
Copy link
Owner

Suor commented Oct 7, 2016

P.S. You can probably rewrite every place you use username to use id and thus solve this for your case. Do you really need 2 unique fields in a model?

@chemary
Copy link
Author

chemary commented Oct 10, 2016

I really only need to cache by username that is why is mostly used by our API, but ManagerMixin._pre_save() is reloading the object by pk, in this case id and this is why I also cached the object by id.

(I don't find clean to make username the pk of the object, we use ids as pks by design.)

@Suor
Copy link
Owner

Suor commented Oct 10, 2016 via email

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

No branches or pull requests

2 participants