Last active
March 17, 2018 10:43
Runs a simple pubsub listener which pushes to clients via sockjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Runs a simple pubsub listener which pushes to clients via sockjs | |
Based on https://gist.github.com/mrjoes/3284402 | |
Eventually I'd like to have one redis connection listening on user_* channel | |
and pushing messages ONLY to that user's client. Currently it just sends | |
a message to everyone. | |
Setup: | |
virtualenv testenv | |
source testenv/bin/activate | |
pip install Tornado>=2.2 sockjs-tornado tornado-redis | |
# assumes redis-server is running on localhost:6379 | |
Running: | |
python server.py | |
# open localhost:8089 in browser | |
redis-cli publish user_12 "Despite being for user_12, this message goes to everyone. Oops" | |
""" | |
import tornado.ioloop | |
import tornado.web | |
import tornadoredis | |
import sockjs.tornado | |
import logging | |
class BrokerConnection(sockjs.tornado.SockJSConnection): | |
clients = set() | |
def on_open(self, request): | |
logging.info('New client at %s' % request.ip) | |
import json | |
logging.info(json.dumps(request.__dict__, indent=2)) | |
self.clients.add(self) | |
def on_close(self): | |
self.clients.remove(self) | |
@classmethod | |
def pubsub(cls, msg): | |
if msg.kind in ['message', 'pmessage']: | |
for c in cls.clients: | |
c.send(msg.body) | |
class IndexHandler(tornado.web.RequestHandler): | |
def get(self): | |
# self.render('client.html') | |
# just to keep the example single-file | |
self.write("""<!DOCTYPE html> | |
<html> | |
<body> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> | |
<script src="http://cdn.sockjs.org/sockjs-0.3.js"></script> | |
<script> | |
var conn; | |
$(function() { | |
conn = new SockJS("/push"); | |
conn.onmessage = function(e) { | |
$('#messages').html('Got: ' + e.data); | |
} | |
var userid = Math.floor((Math.random()*10)+1); // rand b/t 1 and 10 | |
$('#user').html(userid); | |
}); | |
</script> | |
<h4> User <span id="user"></span></h4> | |
<div id="messages"> | |
Listening for messages... | |
</div> | |
</body> | |
</html>""") | |
if __name__ == "__main__": | |
logging.getLogger().setLevel(logging.DEBUG) | |
port = 8090 | |
key = "user_*" | |
rclient = tornadoredis.Client(host='localhost', port=6379) | |
rclient.connect() | |
rclient.psubscribe(key, lambda s: rclient.listen(BrokerConnection.pubsub)) | |
BrokerRouter = sockjs.tornado.SockJSRouter(BrokerConnection, '/push') | |
app = tornado.web.Application( | |
[(r"/", IndexHandler)] + BrokerRouter.urls | |
) | |
app.listen(port) | |
logging.info('Listening on port %d for redis pubsub channel %s', port, key) | |
tornado.ioloop.IOLoop.instance().start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think it can be done like this: https://gist.github.com/Pentusha/5967328