Search code examples
pythontornadocoroutine

Unblock tornado.queues.Queue.get() coroutine when on_connection_close()?


Given a tornado handler that looks like:

class MyHandler(tornado.web.RequestHandler):

    @tornado.gen.coroutine
    def get(self):
        queue = self.getQueue() # returns a tornado.queues.Queue
        _ = yield queue.get()
        self.write("whatever")

    def on_connection_close(self):
        super().on_connection_close()
        # DO SOMETHING HERE THAT BREAKS OUT OF THE YIELD UP THERE??

If the connection closes, I don't really want to remain blocked on the queue, to erroneously pull a value off later. Is there a mechanism I can set up to abort the the blocked get() method?


Solution

  • Use chain_future. Chain queue.get's future with some other future that is in your control (some kind of indicator/flag), then simply resolve flag future on close:

    from tornado.concurrent import Future, chain_future
    
    class MyHandler(tornado.web.RequestHandler):
    
        def initialize(self):
            # of course you can create that in get as well
            self.close_indicator = Future()
    
        @tornado.gen.coroutine
        def get(self):
            queue = self.getQueue() # returns a tornado.queues.Queue
            qget_future = queue.get()
            chain_future(self.close_indicator, qget_future) 
            _ = yield qget_future
            self.write("whatever")
    
        def on_connection_close(self):
            super().on_connection_close()
            # set close indicator by resolving future
            # result will be copied to chained future (qget_future)
            self.close_indicator.set_result(None)