Reputation: 6901
I am trying to make coroutine version of tornado chat demo and i am having trouble understanding it. As i am new to coroutine style of programming and i really hate Callbacks since javascript.
I want to change MessageUpdateHandler to truly use coroutine.
class MessageBuffer(object):
def __init__(self):
self.waiters = set()
self.cache = []
self.cache_size = 200
def wait_for_messages(self, callback, cursor=None):
if cursor:
new_count = 0
for msg in reversed(self.cache):
if msg["id"] == cursor:
break
new_count += 1
if new_count:
callback(self.cache[-new_count:])
return
self.waiters.add(callback)
def cancel_wait(self, callback):
self.waiters.remove(callback)
def new_messages(self, messages):
logging.info("Sending new message to %r listeners", len(self.waiters))
for callback in self.waiters:
try:
callback(messages)
except:
logging.error("Error in waiter callback", exc_info=True)
self.waiters = set()
self.cache.extend(messages)
if len(self.cache) > self.cache_size:
self.cache = self.cache[-self.cache_size:]
# Making this a non-singleton is left as an exercise for the reader.
global_message_buffer = MessageBuffer()
class MessageUpdatesHandler(BaseHandler):
@tornado.web.authenticated
@tornado.web.asynchronous
def post(self):
cursor = self.get_argument("cursor", None)
global_message_buffer.wait_for_messages(self.on_new_messages,
cursor=cursor)
def on_new_messages(self, messages):
# Closed client connection
if self.request.connection.stream.closed():
return
self.finish(dict(messages=messages))
def on_connection_close(self):
global_message_buffer.cancel_wait(self.on_new_messages)
I tried removing @tornado.web.asynchronous
and replaced with @tornado.gen.coroutine
but thats as far as i can go , i do not understand how to yield global_message_buffer.wait_for_messages()
without on_new_messages(self, messages)
callback, as what i understand is it makes callbacks obsolete .
global_message_buffer is designed with a callback but , yeilds do not have callback, so how to yield them?
tornado chat exmaple demo : https://github.com/tornadoweb/tornado/blob/c9af9a7224b1f42e91ad88b0a3f8f10478584b0a/demos/chat/chatdemo.py#L101
Upvotes: 0
Views: 387
Reputation: 261
Here is a simple example, Hope it helps:
class MessageUpdatesHandler(BaseHandler):
@tornado.web.authenticated
@gen.coroutine
def post(self):
cursor = self.get_argument("cursor", None)
messages = yield gen.Task(global_message_buffer.wait_for_messages, cursor=cursor)
if self.request.connection.stream.closed():
return
self.finish(dict(messages=messages))
Upvotes: 1