Server-sent events with Python,Twisted and Flask: is this a correct approach for sleeping? Server-sent events with Python,Twisted and Flask: is this a correct approach for sleeping? flask flask

Server-sent events with Python,Twisted and Flask: is this a correct approach for sleeping?


Your example uses twisted only as a wsgi container. As well as any other thread-based wsgi container it allows you to use time.sleep(1).

It is the case where allowing twisted to handle /my_event_source directly might be beneficial. Here's an example from Using server sent events implemented in Python using twisted:

def cycle(echo):    # Every second, sent a "ping" event.    timestr = datetime.utcnow().isoformat()+"Z"    echo("event: ping\n")    echo('data: ' +  json.dumps(dict(time=timestr)))    echo("\n\n")    # Send a simple message at random intervals.    if random.random() < 0.1:        echo("data: This is a message at time {}\n\n".format(timestr))class SSEResource(resource.Resource):    def render_GET(self, request):        request.setHeader("Content-Type", "text/event-stream")        lc = task.LoopingCall(cycle, request.write)        lc.start(1) # repeat every second        request.notifyFinish().addBoth(lambda _: lc.stop())        return server.NOT_DONE_YET

where the client static/index.html is from the same source:

<!doctype html><title>Using server-sent events</title><ol id="eventlist">nothing sent yet.</ol><script>if (!!window.EventSource) {  var eventList = document.getElementById("eventlist");  var source = new EventSource('/my_event_source');  source.onmessage = function(e) {    var newElement = document.createElement("li");    newElement.innerHTML = "message: " + e.data;    eventList.appendChild(newElement);  }  source.addEventListener("ping", function(e) {    var newElement = document.createElement("li");    var obj = JSON.parse(e.data);    newElement.innerHTML = "ping at " + obj.time;    eventList.appendChild(newElement);  }, false);  source.onerror = function(e) {    alert("EventSource failed.");    source.close();  };}</script>

You could combine it with your wsgi application:

app = Flask(__name__)@app.route('/')def index():    return redirect(url_for('static', filename='index.html'))if __name__ == "__main__":    root = resource.Resource()    root.putChild('', wsgi.WSGIResource(reactor, reactor.getThreadPool(), app))    root.putChild('static', static.File("./static"))    root.putChild('my_event_source', SSEResource())    reactor.listenTCP(8001, server.Site(root))    reactor.run()

WSGIResource expects to handle all urls so the routing code needs to be rewritten to support multiple flask handlers.