Flask-socketio: Accessing to application context in a background task

Created on 5 Mar 2018  路  3Comments  路  Source: miguelgrinberg/Flask-SocketIO

Hi @miguelgrinberg!

Firstly, congratulations for Flask SocketIO.
I have followed the example in https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/example/app.py and it runs ok but I need to access to my database inside the background task and I don't know how to achieve it.

This is the connect event:

@socketio.on('connect', namespace='/rt/notifications/')
def start_notifications_thread():
    logger.info('entra a start')
    global thread
    with thread_lock:
        if thread is None:
            thread = socketio.start_background_task(target=notifications_job)

And this the "notifications_job":

def notifications_job():
    last_alert_id = None
    while True:
        socketio.sleep(60)
        last_id = Alert.get_last_alert_id()  # Flask-SQLAlchemy model
        if last_alert_id is not None and last_id != last_alert_id:
            socketio.emit('new_alerts', {'msg': 'New alert', 'id': last_id}, namespace='/rt/notifications/')
        last_alert_id = last_id

If I execute the previous code then I receive the next error message:

"No application found. Either work inside a view function or push"

question

Most helpful comment

OK! Thank you very much :-)

The correct answer:

def notifications_job():
    last_alert_id = None
    settings_module = os.getenv('FLASK_SETTINGS_MODULE')
    app = create_app(settings_module)
    with app.app_context():
        while True:
            socketio.sleep(60)
            last_id = Alert.get_last_alert_id()  # Flask-SQLAlchemy model
            if last_alert_id is not None and last_id != last_alert_id:
                socketio.emit('new_alerts', {'msg': 'New alert', 'id': last_id}, namespace='/rt/notifications/')
            last_alert_id = last_id

All 3 comments

I think I have found a solution. Simply, I have created an instance of my app inside the notifications_job method and pushed the application context:

def notifications_job():
    last_alert_id = None
    settings_module = os.getenv('FLASK_SETTINGS_MODULE')
    app = create_app(settings_module)
    while True:
        with app.app_context():
            socketio.sleep(60)
            last_id = Alert.get_last_alert_id()  # Flask-SQLAlchemy model
            if last_alert_id is not None and last_id != last_alert_id:
                socketio.emit('new_alerts', {'msg': 'New alert', 'id': last_id}, namespace='/rt/notifications/')
            last_alert_id = last_id

Is this the best approach?

Yes, this is actually the correct approach. You can consider swapping the while and the with, so that a single application context is used, instead of a new one for each while loop iteration, but other than that this looks good.

OK! Thank you very much :-)

The correct answer:

def notifications_job():
    last_alert_id = None
    settings_module = os.getenv('FLASK_SETTINGS_MODULE')
    app = create_app(settings_module)
    with app.app_context():
        while True:
            socketio.sleep(60)
            last_id = Alert.get_last_alert_id()  # Flask-SQLAlchemy model
            if last_alert_id is not None and last_id != last_alert_id:
                socketio.emit('new_alerts', {'msg': 'New alert', 'id': last_id}, namespace='/rt/notifications/')
            last_alert_id = last_id
Was this page helpful?
0 / 5 - 0 ratings

Related issues

EndenDragon picture EndenDragon  路  3Comments

nh916 picture nh916  路  3Comments

benjaminturley picture benjaminturley  路  4Comments

chaitanyavolkaji picture chaitanyavolkaji  路  3Comments

novice79 picture novice79  路  3Comments