Search code examples
pythonflaskblockingserver-sent-events

Server sent events with Flask/Redis: how can more than one client view a stream?


I have multiple clients trying to connect to a server sent events stream at /stream. This works with a single client, but attempting to connect any more clients results in the new client becoming indefinitely blocked waiting for data. If I send more data, it only goes to the first client, and no others.

Here is a small snippet that illustrates my problem:

import flask
import time

app = flask.Flask(__name__)

def event_stream():
    for i in xrange(9999):
        yield "data: %d\n\n" % i
        time.sleep(1)

@app.route("/stream", methods=[ "GET" ])
def stream():
    return flask.Response(
        event_stream(),
        mimetype="text/event-stream"
    )

I then run this with gunicorn --worker-class=gevent -w 4 -t 99999 app:app. It works for a single client, but any others get blocked when issuing GET /stream.

What is the cause of the block, and how should I fix it?

I debugged a little more and got some strange results. If I do this procedure, then this happens:

  • Start client 1 (only client 1 receiving data)
  • Start client 2 (only client 1 receiving data)
  • Start client 3 (only client 1 receiving data)
  • Start client 4 (only client 1 receiving data)
  • Restart client 1 (all 4 clients suddenly start receiving data at the same time)

Solution

  • It turns out that this is something to do with the Chromium web browser, where I was testing. It holds back on making the request until the first one completes, for some reason. Using curl, or an incognito browser session allowed multiple sessions to run at the same time. This means that my problem doesn't really exist in reality, it just appears that way because of the way that Chromium handles simultaneous requests to the same resource.

    I'm not sure quite why Chromium behaves this way, it seems weird. Either way, this isn't a real problem, only a perceived one by my browser.