flask-caching icon indicating copy to clipboard operation
flask-caching copied to clipboard

Proposing a public API for viewing items in the cache

Open wgwz opened this issue 3 years ago • 4 comments

I would like to propose a public API for looking at the items that are presently stored in the cache. This might be a chicken or the egg problem in relation to #243.

The reason I'm proposing this is because I encountered the following problem:

I had a cached endpoint:

@app.route("/summary")
@auth.login_required
@cache.cached(timeout=0, query_string=True)
def summary():
    .... do a bunch of stuff.

Then in a background task, i want to delete the "summary" endpoints caching for all query_string values:

@scheduler.task("cron", id="build_cache_job", minute="*/10")
def build_cache_job():
    ... do some more stuff.
    cache.delete(summary)

To this point it's exactly the same issue mentioned in #243. However the solution I came up with is as follows:

@scheduler.task("cron", id="build_cache_job", minute="*/10")
def build_cache_job():
    ... do some more stuff.
    keys = list(cache.cache._cache.keys())
    for key in keys:
        if key.startswith("/summary"):
            cache.delete(key)

But it appears that I'm using a private API. And that's why I'm asking for a public API for viewing cached items.

As I was writing this I realize that this may be complicated for other backend's like redis. While also having performance implications.

So perhaps it's just better to address #243. But I'll post this anyways in case it's interesting.

wgwz avatar Oct 07 '21 02:10 wgwz

I’m thinking that this is probably not a great idea. I’ve switched to using redis now and once you have redis, why not just interact with that?

wgwz avatar Oct 07 '21 23:10 wgwz

The proposed reason for this API is a bad idea; there’s a reason that there’s an old joke, “the two hardest problems in programming are naming things, cache expiration, and off-by-one errors.”

A better approach to cache expiration is to change how keys are generated in the first place. For example,

_version = 5

def some_func(a,b,c,d):
    return _cached_func(_version, a, b, c, d)

@cache.memoize()
def _cached_func(_version, a, b, c, d):
    # …

This avoids many tricky situations in two-level caches or on backends where there is otherwise no deletion guarantee.

fluffy-critter avatar Dec 31 '21 17:12 fluffy-critter

@fluffy-critter Thanks for the recommendation.

Suppose we scope the conversation just to the public API for viewing cache items, do you agree that’s also a bad idea? If so, it’s probably time to close out this issue.

wgwz avatar Jan 01 '22 17:01 wgwz

Yeah a “view keys” API will generally lead to bad abuses that cause even worse problems down the road. I can see a case for providing a DebugCache wrapper or the like so that folks can track down where particular weirdness comes from, though.

fluffy-critter avatar Jan 01 '22 18:01 fluffy-critter