2

I have been trying to use and Flask-Cache's memoize feature to only return cached results of statusTS(), unless a certain condition is met in another request where the cache is then deleted.

It is not being deleted though, and the Jinja template still displays Online when it should infact display Offline because the server has been stopped. So it is returning a cached result when it should not.

@cache.memoize(60)
def statusTS(sid):
    try:
        server = Server.get_info(sid)
        m = Masters.get_info(server.mid)
        if not m.maintenance:
            tsconn = ts3conn(server.mid)
            tsconn.use(str(server.msid))
            command = tsconn.send_command('serverinfo')
            tsconn.disconnect()
            if not command.data[0]['virtualserver_status'] == 'template':
                return 'Online'

            return 'Unknown'
    except:
        return 'Unknown'

app.jinja_env.globals.update(statusTS=statusTS)

Jinja template:

                              {% if statusTS(server.sid) == 'Online' %}
                        <span class="label label-success">
                          Online
                        </span>{% endif %}

This renders the view:

@app.route('/manage/')
def manage():
    if g.user:
        rl = requests_list(g.user.id)
        admin = User.is_admin(g.user.id)
        g.servers = get_servers_by_uid(g.user.id)
        if 's' in request.args:
            s = request.args.get('s')
            s = literal_eval(s)
        else:
            s = None
        return render_template('manage.html',
                               user=g.user,
                               servers=g.servers,
                               admin=admin,
                               globallimit=Config.get_opts('globallimit'),
                               news=News.get_latest(),
                               form=Form(),
                               masters=Masters.get_all(),
                               treply=rl,
                               s=s)
    else:
        return redirect(url_for('login'))

this is what is supposed to delete the entry.

@app.route('/stop/<id>/')
@limiter.limit("3/minute")
def stop(id):
    if g.user:
        if Server.is_owner(g.user.id, id):
            m = Masters.get_info(Server.get_info(id).mid)
            if not m.maintenance:
                cache.delete_memoized(statusTS, id)
                flash(stopTS(id))
                return redirect(url_for('manage'))
            else:
                flash(
                    'You cannot stop this server while the master is locked for maintenance - please check for further info.')
                return redirect(url_for('manage'))
        else:
            flash(
                'You do not have permission to modify this server - please contact support.')
            return redirect(url_for('manage'))
    else:
        return redirect(url_for('login'))
Ryan
  • 21
  • 3

1 Answers1

0

Your code looks correct. It could be a bug in the whichever backend cache you are using.

Toy example that works:

from flask import Flask
# noinspection PyUnresolvedReferences
from flask.ext.cache import Cache

app = Flask(__name__)
# Check Configuring Flask-Cache section for more details
cache = Cache(app, config={'CACHE_TYPE': 'simple'})


@cache.memoize(timeout=10)
def statusTS(sid):
    print('Cache Miss: {}.'.format(sid))
    return sid


@app.route('/<int:status_id>')
def status(status_id):
    return 'Status: ' + str(statusTS(status_id))


@app.route('/delete/<int:status_id>')
def delete(status_id):
    print('Deleting Cache')
    cache.delete_memoized(statusTS, status_id)
    return 'Cache Deleted'

if __name__ == '__main__':
    app.debug = True
    app.run()

What I think is happening is that the delete is failing. I would step into the cache.delete_memoized(statusTS, status_id) and see if it actually finds and deletes the cached function result. Check werkzeug.contrib.cache.SimpleCache if you are using the cache type simple.

Ciaran Liedeman
  • 779
  • 5
  • 13