3

I'm using Twisted to write a web server. One of the tasks that this server performs takes a long time (~5 minutes). I would like to be able to efficiently notify the client that this task has completed.

I have looked into using Comet/long polling, but for the life of me I can't get the browser to render the data when it receives it.

To prototype this mechanism, I wrote the following:

clock.py

from twisted.internet import reactor, task
from twisted.web.static import File
from twisted.web.server import Site
from twisted.web import server
from twisted.web.resource import Resource
import time

class Clock(Resource):
    def __init__(self):
        self.presence=[]
        loopingCall = task.LoopingCall(self.__print_time)
        loopingCall.start(1, False)
        Resource.__init__(self)

    def render_GET(self, request):
        print "request from",request.getClientIP()
        request.write(time.ctime())
        self.presence.append(request)
        return server.NOT_DONE_YET

    def __print_time(self):
        print "tick"
        for p in self.presence:
            print "pushing data to",p.getClientIP()
            p.write(time.ctime())

root = Resource()
clock = ClockPage()
index = File("index.html")
root.putChild("index.html",index)
root.putChild("clock",clock)
factory = Site(root)
reactor.listenTCP(8080, factory)
reactor.run()

index.html

<html>
<head>
</head>
<body>
<div id="data">Hello</div>
<script type="text/javascript">
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function(){
  if(xhttp.readyState == 4 && xhttp.status == 200){
    alert(xhttp.responseText);
    document.getElementById("data").innerHTML=xhttp.responseText;
  }
};
xhttp.open("GET","clock",true);
xhttp.send(null);
</script>
</body>
</html>

What I've been doing on the server side is calling request.write with the time, every second.

On the client side, all I do is open a XMLHTTPRequest to the appropriate resource and dump the responseText directly into a div whenever .readyState == 4 and .status == 200.

The problem is: the div never gets overwritten and the alert is never called.

I keep reading about using multipart/x-mixed-replace, but I'm not really sure how to use it. Any pointers to tutorials or documentation on implementing this sort of thing in twisted would be greatly appreciated.

duncant
  • 31
  • 1

2 Answers2

0

What about using "HTTP streaming" instead? I have used it successfully to "stream" logs from the server to the "listening" browsers. Here is a simple implementation using twisted and a bit of js: http://codelab.ferrarihaines.com/archives/161

Braudel
  • 11
  • 3
0

Consider adding a p.finish() to your loop, so that the request actually completes. The current implementation will hang forever.

Glyph
  • 31,152
  • 11
  • 87
  • 129