Search code examples
pythonflaskpython-rqflask-cache

Storing a calculation in a flask route cache


I have a long task that goes off into a python-rq worker queue.

@cache.cached(timeout=2592000)
@app.route('/as/<keyword>', methods=['GET'])
@db_session
def auto_suggest(keyword):
    job = q.enqueue(find_keyword, keyword)
    while not job:
        time.sleep(1)
    return jsonify(word=job)

I'm using flask-cache to try and save the result as its a calculation that only needs to be run once a week at most, once a month is sufficient as well.

The problem I am having is when this runs, it caches the failed response, and not the actual solution.

Any other way to do this? Or suggestion in how I should approach this?


Solution

  • You are trying to JSON-encode the Job proxy object, not the result of the job. You do want to check for the job result here:

    job = q.enqueue(find_keyword, keyword)
    while not job.result:
        time.sleep(1)
    return jsonify(word=job.result)
    

    This should be cached just fine.

    You could instead memoize the result of the find_keyword function, using the Cache.memoize() decorator:

    @cache.memoize(30 * 24 * 60 * 60)
    def find_keyword(keyword):
        # ....
    

    This will cache the results of the find_keyword() function for a month, based entirely on the keyword argument (results for different keywords are cached independently).

    One more note: when applying extra decorators to a view function, make sure you put the @app.route() decorator at the top (to be applied last). Any decorator applied 'later' is ignored as it is not their output that is being registered as the view:

    @app.route('/as/<keyword>', methods=['GET'])
    @cache.cached(timeout=2592000)
    @db_session
    def auto_suggest(keyword):
        job = q.enqueue(find_keyword, keyword)
        while not job.result:
            time.sleep(1)
        return jsonify(word=job.result)