Search code examples
pythontornado

Using Tornado To Send Intermittent Updates to Client


I've written a simple tornado application using web-sockets to manage daemons (just like transmission web-interface). One thing that bothers me is the implementation of status update. My WebSocketHandler just recieves messages from client, performs neccessary actions, checks the status and sends it to client. It does not send status to client without request.

class WebSocketHandler(tornado.websocket.WebSocketHandler):

    def open(self):
        print('connected')
        self.daemon = Daemon()
        self.write_message(self.daemon.get_status())

    def on_message(self, message):
        if message == 'start':
            self.daemon.start()
        elif message == 'stop':
            self.daemon.stop()
        self.write_message(self.daemon.get_status())

    def on_close(self):
        print('disconnected')

I'm using setInterval function of javascript on client side to request for status update, like this:

        ws = new WebSocket("ws://localhost:8080/websocket");

        ws.onopen = function () {
          setInterval(function() {
            if (ws.bufferedAmount == 0)
              ws.send('status');
          }, 1000);
        };
    }

How can the same result be achieved on server side, so that tornado sends current status to client without blocking on_message method?


Solution

  • You can use tornado.ioloop.IOLoop.add_timeout to call a method every X number of seconds to update the client:

    from tornado.ioloop import IOLoop
    from datetime import timedelta
    
    class WebSocketHandler(tornado.websocket.WebSocketHandler):
    
        def open(self):
            print('connected')
            self.daemon = Daemon()
            self.write_message(self.daemon.get_status())
            self.schedule_update()
    
        def schedule_update(self):
            self.timeout = IOLoop.instance().add_timeout(timedelta(seconds=5),
                                                         self.update_client)
        def update_client(self):
            try:
                self.write_message(self.daemon.get_status())
            finally:
                self.schedule_update()
    
        def on_close(self):
            IOLoop.instance().remove_timeout(self.timeout)
            print('disconnected')