flask-caching
flask-caching copied to clipboard
Delete memoized versions based on specific parameter only
I have built a REST interface with flask and I'm caching most of the db queries using this extension to minimize db hits during a request. I've done this by outsourcing the db queries into functions and decorating those functions with memoize()
. To invalidate the cache once a db row has been added, modified or deleted, I'm using sqlalchemy events, which call delete_memoized(...)
and delete the memoized versions.
The app has multi tenant capability and all of the tables holding user data have a tenant_id
column. Most of the memoized functions accept a tenant_id
parameter in order to restrict each query to a specific tenant. That has worked very well so far, but in some cases the REST interface must return paginated data and the page parameter is set beforehand by the user. Following my previous approach, I have created a function which accepts the tenant_id
and page
parameters and decorated it with memoize()
:
@cache.memoize()
def get_tenant_documents(tenant_id, page=1, per_page=20):
query = Document.query.filter(Document.tenant_id == tenant_id)
pagination = query.paginate(page=page, per_page=per_page, max_per_page=50)
return pagination
Unfortunately I can't use this approach, because it's not possible to invalidate the cache on a per tenant basis using the value of tenant_id
. I can only delete the cache for all versions of the function (by not passing any parameters to cache.delete_memoized
), but this would clear the cache for all users of course.
It would be nice to have the possibility to delete the memoized versions by a selected argument, which would look like this in my case:
@event.listens_for(Document, "after_insert")
@event.listens_for(Document, "after_update")
@event.listens_for(Document, "after_delete")
def clear_document_cache(
mapper,
connection,
document_obj,
):
cache.delete_memoized(get_tenant_documents, document_obj.tenant_id) # Ignore page, per_page params and delete all versions with that tenant_id
I have looked through the source code a bit but could not find a way to accomplish this. I'm not even sure that this feature can be added to this extension. The only way I can think of is to use the Redis SCAN
command and *
wildcard to find keys matching a specific pattern and deleting them afterwards. Would that be a possible solution? I'm happy to help!
BR