Search code examples
pythontwisted

twisted wait for another client


This is my render_GET function in class inherited from resource.Resource in twisted HTTP server:

    def render_GET(self, request):
           file = request.args['file'][0]
           altitude, azimuth, distance = request.args['position'][0].split(",")
           self.update_render(file, altitude, azimuth, distance, request.args['clientID'][0])
           # update_render() starts a thread that contacts this server again and POSTs data once done
           self.add_client(request.args['clientID'][0])

           while not self.client_data[request.args['clientID'][0]]:
                 # I GET STUCK HERE - the thread CANT send data to this dict since server is locked in this loop
                 time.sleep(0.5)

           return "DONE"

What happens is that I need the twisted server to wait until function update_render does something (this function is asynchronous, so by calling self.update_render() I just start it, not sure when the actual data is written. The return data of update_render() is written in self.client_data dict.

I need to detect the content of this dict in a loop BUT I am stuck there - it seems the server is locked in this loop BUT I need it to respond to other clients (they asynchronously fill self.client_data)


Solution

  • You never want to write a while loop like that in a Twisted-using application.

    Ideally, you want a better API than update_render - one that returns a Deferred. A Deferred gives you a uniform, composable, convenient API for managing callbacks. Callbacks are fairly central to programming with Twisted.

    update_render should use the Deferred's callback method once it gets the client data - instead of putting it into self.client_data. By using the Deferred, it plays nicely in the event-driven system of Twisted. A callback you (the caller) attach to the Deferred can send the result to the client.

    Twisted Web has a slight quirk in that you'll need to return twisted.web.server.NOT_DONE_YET from the render_GET method to let the server know that the response is forthcoming.

    Have a look at Twisted Web In 60 Seconds for some examples of asynchronously generating responses.