I have Tornado chat with export to Redis. Other scripts will export messages from Redis to MongoDB in the time. It works, but how is it written?
def tornadoredis_client():
client = tornadoredis.Client(*configuration.REDIS_CONFIG)
client.connect()
return client
class PlansqTornadoChat(SockJSConnection):
users = dict()
timezones = dict()
def on_open(self, info):
self.authenticated = False
self.timezone = None
self.client = tornadoredis_client()
@tornado.gen.engine
def on_message(self, msg):
data = proto.json_decode(msg)
if data['type'] == 'auth':
if bool(data.get('sid', None)):
try:
int(data['sid']) # check that sid is number, not word
self.user_sid = data['sid']
self.users[self.user_sid] = self
self.user_timezone = yield tornado.gen.Task(self.client.hget, 'timezones', self.user_sid)
self.timezones[self.user_sid] = self.user_timezone
self.authenticated = True
self.send(proto.json_encode({"body": "You was authorized", 'type': 'alert'}))
except Exception, e:
logging.info("bad user's sid: " + str(data['sid']))
else:
self.send(proto.json_encode({"body": "You did not authorize", 'type': 'alert'}))
self.close()
elif data['type'] == 'message':
if all([x in data for x in ['type', 'recipient', 'body', 'sender']]) \
and data['sender'] == self.user_sid:
recipient = data['recipient']
try:
int(recipient) # check that sid is number, not word
except Exception, e:
logging.info('sid of recipient is not number')
return
self.thread = "_".join([str(x) for x in sorted([int(self.user_sid), int(recipient)])])
# Save to Redis
data_to_send = {
'thread_id': self.thread,
'sender': self.user_sid,
'recipient': recipient,
'body': data['body'],
'datetime': (datetime.now() - datetime(1970, 1, 1)).total_seconds()
}
yield tornado.gen.Task(self.client.sadd, "thread:" + self.thread, proto.json_encode(data_to_send))
yield tornado.gen.Task(self.client.sadd, 'new_threads:all', "thread:" + self.thread)
# Send to Socket
data_to_send['type'] = 'message'
# if user is online
if recipient in self.users:
data_to_send['datetime'] = utc_to_localtime(data_to_send['datetime'], self.timezones[recipient])
self.users[recipient].send(proto.json_encode(data_to_send))
data_to_send['datetime'] = utc_to_localtime(data_to_send['datetime'], self.user_timezone)
self.send(proto.json_encode(data_to_send))
else:
logging.info('Bad request: ' + str(data))
else:
logging.info('Bad request: ' + str(data))
def on_close(self):
del self.users[self.user_sid]
del self.timezones[self.user_sid]
self.client.disconnect()
My configuration in configuration of main application (Flask + MongoDB). There only Redis configuration (host and port).
The rest of the code:
if __name__ == '__main__':
logging.getLogger().setLevel(logging.DEBUG)
logging.getLogger().setLevel(logging.INFO)
EchoRouter = SockJSRouter(PlansqTornadoChat, '/socket')
app = web.Application(EchoRouter.urls)
app.listen(configuration.TORNADO_PORT)
ioloop.IOLoop.instance().start()