Let's start with some example. There is library tornado-redis and below is example of using it.
import tornadoredis
import tornado.web
import tornado.gen
c = tornadoredis.Client()
c.connect()
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
foo = yield tornado.gen.Task(c.get, 'foo')
bar = yield tornado.gen.Task(c.get, 'bar')
zar = yield tornado.gen.Task(c.get, 'zar')
self.set_header('Content-Type', 'text/html')
self.render("template.html", title="Simple demo", foo=foo, bar=bar, zar=zar)
And everything is simple. But I need to write a wrapper class. There is no problem with coding for me, but I think I am mistaken with async pattern.
My wrapper class should call redis class asynchronously, right!? Now do I have to implement my class also asynchronously in the way that the handler could call it with Task (async)? Then I would have two async places. What is the right way to keep Tronado async and keep it simple?
Handler --async call--> MyWrapper --async call--> tronado-redis
or
Handler --sync call--> MyWrapper --async call--> tronado-redis
or
Handler --async call--> MyWrapper --sync call--> tronado-redis
Asynchronous functions can only be called by other asynchronous functions. Since tornado-redis is asynchronous, the RequestHandler and everything in between must also be asynchronous.
Note that the @tornado.web.asynchronous
decorator is only used on RequestHandler methods - to make asynchronous methods outside of a RequestHandler you can use @gen.coroutine
or @gen.engine
by itself.