Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

server sent event to multiple clients from Flask

I am playing around with a small project to get a better understanding of web technologies. One requirement is that if multiple clients have access to my site, and one make a change all the others should be notified. From what I have gathered Server Sent events seems to do what I want. However when I open my site in both Firefox and Chrome and try to send an event, only one of the browsers gets it. If I send an event again only one of the browsers gets the new event, usually the browser that did not get event number one.

Here is the relevant code snippets.

Client:

console.log("setting sse handlers")
viewEventSource = new EventSource("{{ url_for('viewEventRequest') }}");
viewEventSource.onmessage = handleViewEvent;

function handleViewEvent(event){
    console.log("called handle view event")
    console.log(event);
}

Server:

@app.route('/3-3-3/view-event')
def view_event_request():
    return Response(handle_view_event(), mimetype='text/event-stream')

def handle_view_event():
while True:
    for message in pubsub_view.listen():
        if message['type'] == 'message':
            data = 'retry: 1\n'
            data += 'data: ' + message['data'] + '\n\n'
            return data

@app.route('/3-3-3/test')
def test():
    red.publish('view-event', "This is a test message")
    return make_response("success", 200)

My question is, how do I get the event send to all connected clients and not just one?

like image 709
morras Avatar asked Nov 12 '22 13:11

morras


1 Answers

Here are some gists that may help (I've been meaning to release something like 'flask-sse' based on 'django-sse):

https://gist.github.com/3680055

https://gist.github.com/3687523

also useful - https://github.com/jkbr/chat/blob/master/app.py

The first thing I notice about your code is that 'handle_view_event' is not a generator. Though it is in a 'while' loop, the use of 'return' will always exit the function the first time we return data; a function can only return once. I think you want it to be 'yield' instead.

In any case, the above links should give you an example of a working setup.

As Anarov says, websockets and socket.io are also an option, but SSE should work anyway. I think socket.io supports using SSE if ws are not needed.

like image 89
Chris2048 Avatar answered Nov 15 '22 05:11

Chris2048