Search code examples
pythontornadolong-polling

Tornado @gen.coroutine closes long polling connection


Hi i have a problem with Tornado framework implementing long polling. The post method of my requesthandler is decorated with both @asynchronous and @gen.coroutine. When i leave it hanging for a callback to be called in order to write back to the client, the connection is immediately closed. I saw that this is related to the use of @gen.coroutine that automatically calls self.finish() when all futures have been yielded. I need this decorator because i'm using Mongo Motor. A short example below:

@web.asynchronous
@gen.coroutine
def post(self):
  #mongo Motor yielding code  
  notifications.register_callback(self.on_message)

Notifications is a global object that keeps an array of callbacks and calls them upon receiveing a message from outside. Thanks


Solution

  • You need to use @gen.engine instead of @gen.coroutine if you want to use yield to call coroutines, but not have self.finish() called automatically at the end of the handler. There's a comment in the code of the @web.asynchronous decorator that notes this:

    # If @asynchronous is used with @gen.coroutine, (but
    # not @gen.engine), we can automatically finish the
    # request when the future resolves.  Additionally,
    # the Future will swallow any exceptions so we need
    # to throw them back out to the stack context to finish
    # the request.
    

    So, if @asynchronous is used with @gen.coroutine, it will automatically call self.finish, but it will skip it if used with @gen.engine.