forked from abourget/pyramid_socketio
-
Notifications
You must be signed in to change notification settings - Fork 0
Gevent-based Socket.IO integration layer for Pyramid
License
samuelrayment/pyramid_socketio
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
#################### CHECK OUT THIS POST: http://blog.abourget.net/2011/3/17/new-and-hot-part-4-pyramid-socket-io-gevent/ #################### The following is a bit rude and rough, check the blog post instead Gevent-based Socket.IO integration for Pyramid (and WSGI frameworks) ==================================================================== To use the server, either run: <pre> socketio-serve development.ini socketio-serve-reload development.ini </pre> or tweak your <code>[server:main]</code> section in your development.ini to: <pre> [server:main] use = egg:pyramid_socketio#sioserver_patched resource = socket.io host = 0.0.0.0 port = 6555 </pre> otherwise, follow instructions given for <code>pastegevent</code>. Simple in-Pyramid usage: <pre> ### somewhere in a Pyramid view: from pyramid_socketio import SocketIOContext, socketio_manage class ConnectIOContext(SocketIOContext): """Starting context, which will go one side or the other""" def msg_connect(self, msg): if msg.get('context') not in contexts: self.io.send(dict(type="error", error="unknown_connect_context", msg="You asked for a context that doesn't exist")) return # Waiting for a msg such as: {'type': connect', 'context': 'section'} newctx = self.switch(contexts[msg['context']]) if hasattr(newctx, 'startup'): newctx.startup(msg) # Returning a new IOContext switches the WebSocket context, and will # call this context's methods for next incoming messages. return newctx def msg_login(self, msg): # Do the login, then wait for the next connect self.request.session.user_id = 123 print "Logged in, session created and" class SectionIOContext(SocketIOContext): def startup(self, connect_msg): print "Started the section context" self.my_id = connect_msg['section_id'] # TODO: make sure we don't leak Sessions from MongoDB! from intr.models import mdb # can't import globally, because of Pyramid self.db = mdb self.conn = BrokerConnection("localhost", "guest", "guest", "/") self.chan = self.conn.channel() self.queue = Queue("session-%s" % self.io.session.session_id, exchange=my_exchange, durable=False, exclusive=True, auto_delete=True, routing_key="section.%s" % self.my_id) self.producer = Producer(self.chan, exchange=my_exchange, serializer="json", routing_key="section.%s" % self.my_id) self.producer.declare() self.consumer = Consumer(self.chan, [self.queue]) self.consumer.declare() self.consumer.register_callback(self.consume_queue_message) self.spawn(self.queue_recv) # Do we need this ? Please fix the session instead, have a new one # init'd for each incoming msg, or when calling save(), re-create a new # SessionObject. request = self.request self.user = request.session['user'] self.temporary = request.session['temporary'] self.user_id = request.session['user_id'] def consume_queue_message(self, body, message): """Callback when receiving anew message from Message Queue""" # Do something when received :) print "Received message from queue:", self.io.session.session_id, body self.io.send(body) def queue_recv(self): """Wait for messages from Queue""" self.consumer.consume(no_ack=True) # consume queue... while True: gevent.sleep(0) self.conn.drain_events() if not self.io.connected(): return # # Socket messages # def msg_memorize(self, msg): # "memorized" is the 'type' attribute, any other kwarg added will be # added to the JSON object. self.msg("memorized", some="thing") def msg_forget(self, msg): self.error("error_code", "Error message") def msg_change_privacy(self, msg): pass def msg_get_members(self, msg): pass def msg_enter_game(self, msg): return self.switch(SomeOtherIOContext) contexts = {'section': SectionIOContext, 'somewhereelse': SocketIOContext, } # # SOCKET.IO implementation # @view_config(route_name="socket_io") def socket_io(request): """Deal with the SocketIO protocol, using SocketIOContext objects""" # Offload management to the pyramid_socketio module retval = socketio_manage(ConnectIOContext(request)) #print "socketio_manage ended" return Response(retval) #### Inside __init__.py for your Pyramid application: def main(..): ... config.add_static_view('socket.io/lib', 'intr:static') config.add_route('socket_io', 'socket.io/*remaining') .... </pre> In the routes and view configurations, 'socket.io' is the "resource" specified either in the server (under [server:main], key=resource), and is by default "socket.io". This is pretty much a standard.. # # On the JavaScript side: # Somewhere: <script src="http://cdn.socket.io/stable/socket.io.js"></script> And then: var socket = new io.Socket(null, {rememberTransport: false, transports: ['websocket', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']}); socket.on('message', function(obj){ console.log("message:", JSON.stringify(obj)); if ((obj.type == "memorized") || (obj.type == "forgot")) { // do some tihngs... } else if (obj.type == "new_content") { $("div.intr-timeline").append($(obj.insert_html)); } else if (obj.type == "privacy_changed") { $("#privacy").val(obj.new_value); } else if (obj.type == "photos_sent") { $('#intrentry-post-photos div.upload').empty(); new_upload_box(); } }); socket.on('error', function(obj) { console.log("error", obj); }); socket.on('disconnect', function(obj) { console.log("disconnected", obj); socketio_notification("Disconnected", "There was a disconnection, either because of network or server failure"); socketio_schedule_reconnect(); }); var connection_notification = null; socket.on('connect', function() { console.log("connected"); // Comment out if you don't use the auto-reconnect machinery: socketio_notification(); socket.send({type: "connect", context: "interest", interest_id: "${intr['_id']}"}); }); // Use this: socket.connect(); // Or this is optional auto-reconnect machinery: function socketio_schedule_reconnect() { setTimeout(function() { if (!socket.connected && !socket.connecting) { socketio_reconnect("reconnect");}}, 1000); } function socketio_reconnect(func) { console.log("connecting... ", socket); if (func == "connect") { socketio_notification("Connecting", "Connecting..."); } if (func == "reconnect") { socketio_notification("Re-connecting", "Attempting to reconnect..."); socketio_schedule_reconnect(); } socket.connect(); } function socketio_notification(title, msg) { if (connection_notification) { connection_notification.close(); connection_notification = null; } if (title) { connection_notification = notify_default(title, msg); } } $(document).ready(function() { socketio_reconnect('connect'); });
About
Gevent-based Socket.IO integration layer for Pyramid
Resources
License
Stars
Watchers
Forks
Packages 0
No packages published
Languages
- Python 100.0%