class Handler(RequestHandler): @asynchronous def get(self): self.client = Client() self.client.connect() self.client.subscribe("foo", callback=self.on_receive) def on_receive(self, msg): """ New message, close out connection. """ msg_type, msg_channel, msg = msg if msg_type == "message": self.finish({"message": msg})
class Handler(RequestHandler): @asynchronous def get(self): self.client = Client() self.client.connect() self.client.subscribe("foo", callback=self.on_receive) def on_receive(self, msg): """ New message, close out connection. """ msg_type, msg_channel, msg = msg if msg_type == b"message": self.finish({"message": msg.decode()})
class RedisWebSocket(tornado.websocket.WebSocketHandler): client = None user = None channel = None io_loop = tornado.ioloop.IOLoop.instance() def open(self): # Get user and channel self.user = self.get_argument('user', None) self.channel = self.get_argument('channel', None) # new access self.application.db.access.insert_one(Access.connect(self.user,self.channel).__dict__) # get all messages messages = self.application.db.messages.find({"channel" : self.channel}).sort("$natural",pymongo.DESCENDING) output = [format_entity(msg) for msg in messages] for message in reversed(output): self.write_message(message) # subscribe to channel self.client = ToRedisClient() self.client.connect(host="redis") self.client.subscribe(self.channel, callback=self.on_receive) def on_receive(self,msg): msg_type, msg_channel, msg = msg if msg_type == b"message": self.write_message(eval(msg)) # client.write_message(message) def on_message(self, message): entity = Message.from_dict(json.loads(message)) self.application.db.messages.insert_one(entity.__dict__) conn = ToRedisClient() conn.connect(host="redis") def publish_message(channel,message): conn.publish(channel,message) self.io_loop.add_timeout(time.time(), partial(publish_message,self.channel,format_entity(entity.__dict__))) # self.application.manager.notify(entity.channel,format_entity(entity.__dict__)) def on_close(self): self.application.db.access.insert_one(Access.disconnect(self.user, self.channel).__dict__) self.client.unsubscribe(self.channel)
class MessageHandler(WebSocketHandler): def __init__(self, *args, **kwargs): super(MessageHandler, self).__init__(*args, **kwargs) self.r_server = Redis() self.redis = Client() self.redis.connect() def get_current_user(self): user = self.get_secure_cookie("user") if user is None: return '' else: return user.strip('" ') def on_message(self, msg): msginfo = loads(msg) # listens for handshake from page self.channel = msginfo['user'] # need to split the rest off to new func so it can be asynchronous self.listen() def listen(self): # runs task given, with the yield required to get returned value # equivalent of callback/wait pairing from tornado.gen self.redis.subscribe(self.channel, callback=self.callback) # fight race condition by loading from redis after listen started oldmessages = self.r_server.lrange('%s:messages' % self.channel, 0, -1) if oldmessages is not None: for message in oldmessages: self.write_message(message) def callback(self, msg): if msg[0] == 'message': self.write_message(msg[2]) @engine def on_close(self): yield Task(self.redis.unsubscribe, self.channel) self.redis.disconnect()
class ChatSocketHandler(UserMixin, tornado.websocket.WebSocketHandler): cache_size = 30 commands_client = Client() pub_client = Client() def open(self): # FIXME: make chat_channel dynamic self.chat_channel = "chat" self.chat_userset = chat_userset_key(self.chat_channel) self.from_user = self.get_current_user()['name'] host, port = options.redis.split(":") self.sub_client = Client() self.sub_client.connect(host, int(port)) logging.debug("Opened subscribe connection to redis for user=%s", self.from_user) # first add entered user in user_set, then subscribe to notifications def sadd_finished(resp): self.sub_client.subscribe(self.chat_channel, callback=self.on_redis_message) self.sub_client.sadd(self.chat_userset, self.from_user, callback=sadd_finished) logging.info("%s joined the chat", self.from_user) ChatSocketHandler.send_message(self.chat_channel, self.from_user, "joined the chat", system=True) def on_redis_message(self, msg): msg_type, msg_channel, msg = msg logging.debug("Got message from Redis: type=%s, channel=%s, msg=%s", msg_type, msg_channel, msg) if msg_type == b"message": # write message back to websocket self.write_message(json.loads(msg.decode())) def on_close(self): logging.info("%s left the chat", self.from_user) self.sub_client.srem(self.chat_userset, self.from_user) ChatSocketHandler.send_message(self.chat_channel, self.from_user, "left the chat", system=True) def on_message(self, message): logging.info("got message %r", message) ChatSocketHandler.send_message(self.chat_channel, self.from_user, message) @classmethod def update_lastmessages(cls, chat_channel, chat): cls.pub_client.lpush(chat_lastmessages_key(chat_channel), json.dumps(chat)) cls.pub_client.ltrim(chat_lastmessages_key(chat_channel), 0, cls.cache_size) @classmethod def last_messages(cls, chat_channel, callback): """get last messages""" if not cls.commands_client.is_connected(): host, port = options.redis.split(":") cls.commands_client.connect(host, int(port)) logging.debug("Opened commands connection to redis") def transform(response): json_resp = [json.loads(x.decode("utf8")) for x in response] callback(json_resp[::-1]) cls.commands_client.lrange(chat_lastmessages_key(chat_channel), 0, cls.cache_size, callback=transform) @classmethod def current_users(cls, chat_channel, callback): """get last messages""" if not cls.commands_client.is_connected(): host, port = options.redis.split(":") cls.commands_client.connect(host, int(port)) logging.debug("Opened commands connection to redis") def transform(response): json_resp = [x.decode("utf8") for x in response] callback(json_resp) cls.commands_client.smembers(chat_userset_key(chat_channel), callback=transform) @classmethod def send_message(cls, chat_channel, from_user, body, system=False): if not cls.pub_client.is_connected(): host, port = options.redis.split(":") cls.pub_client.connect(host, int(port)) logging.debug("Opened publish connection to redis") if not system: body = message_beautify(body) chat_msg = { "id": str(uuid.uuid4()), "from": from_user, "when": datetime.now().strftime("%Y-%m-%d %H:%M"), "body": body, "system": system, } cls.update_lastmessages(chat_channel, chat_msg) logging.debug("Broadcasting message %s", chat_msg) cls.pub_client.publish(chat_channel, json.dumps(chat_msg))
if message_type == 'landing:track:change': for participant in RouterConnection.participants: if participant.user_id == 'anonymous': participant.send(message_data) elif message_type == 'admin:': user_id = data.get('user_id', None) for participant in RouterConnection.participants: if participant.user_id == user_id: participant.send(message_data) application = tornado.web.Application( sockjs.tornado.SockJSRouter(RouterConnection, '/sock').urls ) if __name__ == '__main__': parse_command_line() import logging logging.getLogger().setLevel(logging.DEBUG) http_server = tornado.httpserver.HTTPServer(application) http_server.listen(options.port, address=options.host) client = Client() client.connect() client.subscribe('tornado_events', callback=tornado_events) tornado.ioloop.IOLoop.instance().start()