цепочка асинхронных операций перед записью на клиент (python - торнадо)

В простом асинхронном случае обработчик может выглядеть так:

@tornado.web.authenticated
@tornado.web.asynchronous
def post(self):
    AsyncHTTPClient().fetch("http://api.example.com/", self.on_post_response)

def on_post_response(self, response):
    self.render("template.html", status=response.error)

Однако я дошел до того, что мне нужно выполнить две асинхронные операции (извлечение удаленного API-интерфейса, а затем отправка почты с результатами) перед возвратом к клиенту.

Интересно, есть ли "встроенный" способ сделать это, например. путем добавления обратных вызовов в очередь (например, ioloop.add_callback) или мне нужно составить собственный объект, который будет управлять этими задачами и их состоянием и вызывать его из post.


person Tzury Bar Yochay    schedule 21.02.2012    source источник


Ответы (1)


Рассматривали ли вы следующий подход?

@tornado.web.authenticated
@tornado.web.asynchronous
def post(self):
    async_fetch(..., self._on_fetch_response)

def _on_fetch_response(self, response):
    async_mail(response, self._on_mail_response)

def _on_mail_response(self, response):
    self.render(...) # render() automatically calls self.finish()

Или с помощью tornado.gen:

@asynchronous
@gen.engine
def post(self):
    fetch_response = yield gen.Task(async_fetch, ...)
    mail_response = yield gen.Task(async_mail, ...)
    self.render(...)
person jholster    schedule 21.02.2012
comment
Можете ли вы помочь определить async_mail тогда, похоже, это настоящая помощь, которая мне нужна ;-), делает ли добавление декоратора @asynchronous каждую функцию асинхронной? - person Tzury Bar Yochay; 21.02.2012
comment
async_email() был просто вымышленным примером, см. tornadomail для асинхронного SMTP-клиента. Декоратор @asynchronous делает сам метод обработчика запроса асинхронным, но код внутри обработчика по-прежнему блокируется, если он явно не поддерживает неблокирующее выполнение, например. через параметр обратного вызова. Таким образом, вам нужны специальные версии библиотек ввода-вывода (почта, http, база данных), чтобы воспользоваться преимуществами асинхронности. gen.Task — это просто синтаксический сахар для того же самого. - person jholster; 21.02.2012