Running an async background task in Tornado

前端 未结 5 1425
北荒
北荒 2020-12-15 06:50

Reading the Tornado documentation, it\'s very clear how to call an async function to return a response:

class GenAsyncHandler(RequestHandler):
    @gen.corou         


        
5条回答
  •  不思量自难忘°
    2020-12-15 07:09

    Here's my answer in 2019!

    Start with some slow non-blocking code. See: http://www.tornadoweb.org/en/stable/faq.html#id2

    async def _do_slow_task(self, pk):
        await asyncio.sleep(pk)
        logger.info(f'Finished slow task after {pk} seconds')
    

    See here to understand the difference between async and blocking: http://www.tornadoweb.org/en/stable/guide/async.html#asynchronous-and-non-blocking-i-o

    Then, make your request method a coroutine with the async/await syntax, which makes it non-blocking in order to handle multiple requests in parallel.

    async def post(self):
        """Make a few requests with different pks and you should see that
            the numbers logged are in ascending order.
        """
        pk = self.get_query_argument('pk')
        try:
            record = await self.db_queryone(
                f"SELECT * FROM records WHERE id = {int(pk)};"
            )
        except Exception as e:
            self.set_status(400)
            self.write(str(e))
            return
        await self._do_slow_task(pk)
        self.write(f'Received {pk}')
    

    Now, modify the method a bit to run in the background or

    “fire and forget” a coroutine without waiting for its result

    so that the client receives a response right away. See: http://www.tornadoweb.org/en/stable/guide/coroutines.html#how-to-call-a-coroutine

    async def post(self):
        """Make a few requests with different pks and you should see responses
            right away, and eventually log messages with the numbers in
            ascending order.
        """
        pk = self.get_query_argument('pk')
        try:
            record = await self.db_queryone(
                f"SELECT * FROM records WHERE id = {int(pk)};"
            )
        except Exception as e:
            self.set_status(400)
            self.write(str(e))
            return
        IOLoop.current().spawn_callback(self._do_slow_task, pk)
        self.write(f'Received {pk}')
    

提交回复
热议问题