Generator-based asynchronous interfaceΒΆ
tornadio2.gen
module is a wrapper around tornado.gen
API. You might want to take a
look at Tornado documentation for this module, which can be found here.
While you can use tornado.gen
API without any problems, sometimes you may want to handle your messages in
order they were received. If you will decorate your functions with tornado.gen.engine
, your code will work asynchronously -
second message might get handled before first message got processed.
To prevent this situation, TornadIO2 provides helpful decorator: tornadio2.gen.sync_engine
. sync_engine
will queue incoming
calls if there’s another instance of the function running. As a result, it will call your method synchronously without
blocking the io_loop. This decorator only works with class methods, don’t try to use it for functions - it requires self
to properly function.
Lets check following example:
from tornadio2 import gen
class MyConnection(SocketConnection):
@gen.sync_engine
def on_message(self, query):
http_client = AsyncHTTPClient()
response = yield gen.Task(http_client.fetch, 'http://google.com?q=' + query)
self.send(response.body)
If client will quickly send two messages, it will work “synchronously” - on_message
won’t be called for second message
till handling of first message is finished.
However, if you will change decorator to gen.engine
, message handling will be asynchronous and might be out of order:
from tornadio2 import gen
class MyConnection(SocketConnection):
@gen.engine
def on_message(self, query):
http_client = AsyncHTTPClient()
response = yield gen.Task(http_client.fetch, 'http://google.com?q=' + query)
self.send(response.body)
If client will quickly send two messages, server will send response as soon as response is ready and if it takes longer to handle first message, response for second message will be sent first.
As a nice feature, you can also decorate your event handlers or even wrap main on_event
method, so
all events can be synchronous when using asynchronous calls.
tornadio2.gen
API will only work with the yield
based methods (methods that produce generators). If you implement your
asynchronous code using explicit callbacks, it is up for you how to synchronize their execution order.
TBD: performance considerations, python iterator performance.