Reputation: 134671
I have lot of code in my Tornado app which looks like this:
@tornado.web.asynchronous
def get(self):
...
some_async_call(..., callback=self._step1)
def _step1(self, response):
...
some_async_call(..., callback=self._step2)
def _step2(self, response):
...
some_async_call(..., callback=self._finish_request)
def _finish_request(self, response):
...
self.write(something)
self.finish()
Obviously inline callbacks would simplify that code a lot, it would look something like:
@inlineCallbacks
@tornado.web.asynchronous
def get(self):
...
response = yield some_async_call(...)
...
response = yield some_async_call(...)
...
response = yield some_async_call(...)
...
self.write(something)
self.finish()
Is there a way of having inline callbacks or otherwise simplifying the code in Tornado?
Upvotes: 2
Views: 402
Reputation: 1847
You could even factorize the calls.
I think what you do calls one async call after the other, thus not giving a maximum latency improvement.
If the calls don't have any dependencies (like e.g. taking the result of one call to do the second call) you could start all calls simultaneously:
@tornado.web.asynchronous
@gen.engine
def get(self):
responses = yield [ gen.Task(call) for call in required_calls ]
This way, all calls start at the same time and thus your overall latency is the max(all calls) instead of the sum(all calls).
I've used this in an app that need to aggregate many third-party WS or database calls and it improves the overall latency a lot.
Of course it doesn't work if there are dependencies between the calls (as mentionned above)
Upvotes: 4
Reputation: 31910
You might also consider just using Cyclone, which would allow you to use @inlineCallbacks
(and any other Twisted code that you want) directly.
Upvotes: 2
Reputation: 134671
Found it. In Tornado it's not called inline callbacks, but rather "a generator-based interface" — tornado.gen
. Thus my code should look something like:
@tornado.web.asynchronous
@gen.engine
def get(self):
...
response = yield gen.Task(some_async_call(...))
...
response = yield gen.Task(some_async_call(...))
...
response = yield gen.Task(some_async_call(...))
...
self.write(something)
self.finish()
Upvotes: 2