верижно свързване на асинхронни операции преди запис на клиент (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 прави самия метод на обработка на заявки асинхронен, но кодът вътре в манипулатора все още блокира, освен ако изрично не поддържа неблокиращо изпълнение, напр. чрез параметър за обратно извикване. Следователно имате нужда от специални версии на IO библиотеки (поща, http, база данни), за да се възползвате от асинхронността. gen.Task е просто синтактична захар за същото нещо. - person jholster; 21.02.2012