Flask-socketio: Sending multiple emits buffers and sends all at once

Created on 8 Apr 2015  路  8Comments  路  Source: miguelgrinberg/Flask-SocketIO

I get all events sent to the browser at once, at the end.

@socketio.on('foo')
def foo():
    emit('foo','foo')
    time.sleep(1) 
    emit('foo','bar')
    time.sleep(1)
    emit('foo','baz')

Will I have to use threads like in this example?

Thanks

Most helpful comment

This is a pretty specific use case but hopefully it'll save somebody some pain in the future. If you're using eventlet to run your Flask_SocketIO server and you use python multiprocessing, do not do the monkey patch. It's not compatible: https://github.com/eventlet/eventlet/issues/425#issuecomment-314985945.

Instead, call eventlet.sleep(0) or socketio.sleep(0) to trigger a flush after your emit. Thanks to the answers in https://stackoverflow.com/questions/32720668/flask-and-flask-socketio-flush-all-emit-events for the tips.

All 8 comments

@infrared is your time.sleep() call monkey patched by gevent?

Ah.

monkey.patch_all()

..has made a difference. Thanks for the response.

Sorry for digging up old threads, but I am running into the same problem as described by OP, where I am using time.sleep(1.0) to simulate progresses. As described, all emits are sent to the browser all at once.

I added the following two lines on the very top of the main file

import gevent.monkey
gevent.monkey.patch_all()

But that does not make a difference. I am running on Flask-SocketIO 2.9.3 and gevent 1.2.2

Thank you for your help.

@mckuok not really sure how I can help. Do you have your code available somewhere I can see it?

Thank you. I would expect the ul gets populated with 1 new step li every 1 second. But as described above, all the events are 'buffered' and get flushed when the start_analysis function finishes, resulting in all li appended at once.

python main.py

from gevent import monkey
monkey.patch_time()

@socketio.on('connect', namespace='/status')
def start_analysis():
    for step in AnalysisEngine.get_steps():
        emit(step.get_running_event(), step.get_step())
        step.execute()
        time.sleep(1)
        emit(step.get_finished_event(), step.get_step())

status.html

socket.on('connect', function() {

        socket.on('event1', function(step) {
            const ul = document.getElementById("statuses");
            const li = document.createElement("li");
            li.appendChild(document.createTextNode('event1' + ': ' + step));
            ul.appendChild(li);
        });

        socket.on('event2', function(step) {
            const ul = document.getElementById("statuses");
            const li = document.createElement("li");
            li.appendChild(document.createTextNode('event2' + ': ' + step));
            ul.appendChild(li);
        });
...
}

were you able to figure this out? I've tried everything ( I think ) and I still can't get that working .. just sends them all at once at the end

@supertux11 this is usually lack of monkey patching. Make sure all the functions that you are using are either safe for gevent/eventlet, or are monkey patched.

This is a pretty specific use case but hopefully it'll save somebody some pain in the future. If you're using eventlet to run your Flask_SocketIO server and you use python multiprocessing, do not do the monkey patch. It's not compatible: https://github.com/eventlet/eventlet/issues/425#issuecomment-314985945.

Instead, call eventlet.sleep(0) or socketio.sleep(0) to trigger a flush after your emit. Thanks to the answers in https://stackoverflow.com/questions/32720668/flask-and-flask-socketio-flush-all-emit-events for the tips.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benjaminturley picture benjaminturley  路  4Comments

j2logo picture j2logo  路  3Comments

chaitanyavolkaji picture chaitanyavolkaji  路  3Comments

dlernz picture dlernz  路  4Comments

lnunno picture lnunno  路  4Comments