Search code examples
pythonflaskflask-caching

caching.memoize & response_filter for internal server errors


I am using flask_caching to cache responses of my flask API. I am using the decorator on my routes like this

import random
class Status(Resource):
  @cache.memoize(timeout=60)  # cache for a minute
  def post(self):

    return random.randint(0, 5)

which will return the same random number for a minute. However, what if the random function (read: "any functionality inside the route") breaks, and the route returns a 500 internal server error? As far as I know, flask_caching would be caching this, and return the bad response for all further calls within a minute, which is not what I want.

I read into this and found the response_filter parameter, which can be added to the decorator easily, seemingly specifically to prevent this from happening ("Useful to prevent caching of code 500 responses.", from the docs:

https://flask-caching.readthedocs.io/en/latest/api.html?highlight=response_filter#flask_caching.Cache.memoize)

@cache.memoize(timeout=60, response_filter=callable_check_for_500(???))

However, I am unable to find an example of this use case. It says "If the callable returns False, the content will not be cached." - how do I implement this callable to check if the status code is 500? Any links or ideas appreciated


Solution

  • I figured out "a solution", but I'm not entirely happy with it

    basically, the check_500() function gets the argument resp by default, however its not the full response object, and unfortunately lacks the status_code attribute, like I expected.

    the status code itself is in the data, and I'm just looking at the last entry of the response, which is all the data returned. In my case its just the returned json as [0], and the status_code at [-1].

    implementation is currently as follows:

      @cache.memoize(timeout=60, response_filter=check_500)  # cache for a minute
    

    with the callable check_500 function defined above

    def check_500(resp):
      if resp[-1] == 500:
          return False
      else:
          return True
    

    This works pretty much like above_c_level suggested in the comment, so thank you very much, however I would advise to look at the last index of the response instead of checking if 500 is in the response data at all. It still seems a bit wonky, if anyone has a more elaborate idea, feel free to post another answer.