]> git.zarvox.org Git - imoo.git/commitdiff
Allow multiple ribbon worker processes in different folders
authorDrew Fisher <drew.m.fisher@gmail.com>
Tue, 13 May 2014 07:15:54 +0000 (00:15 -0700)
committerDrew Fisher <drew.m.fisher@gmail.com>
Wed, 14 May 2014 04:14:58 +0000 (21:14 -0700)
For now, spawn one ribbon per websocket. This will likely need to be revised
later.

reactornado/dispatcher.js
reactornado/ribbon_passthrough.py

index 9dfcda80e37ae9079df134ceedad61006caa05a8..cca1a46b1dc421ca30bc22eb6197e54ee5833e65 100644 (file)
@@ -14,6 +14,8 @@ var Dispatcher = {
             this.handle_blist_message(obj.method, obj.params);
         } else if (obj.sender == "conversations") {
             this.handle_conversations_message(obj.method, obj.params);
+        } else if (obj.sender == "session") {
+            this.handle_session_message(obj.method, obj.params);
         }
     },
     handle_blist_message: function(method, params) {
@@ -30,7 +32,9 @@ var Dispatcher = {
         if (method == "buddy_status_changed") {
             window.blist[bid].status = params.status;
         } else if (method == "buddy_icon_changed") {
-            window.blist[bid].bicon_url = params.url;
+            var url = "/icons/" + window.session_id + "/" + params.url;
+            console.log(url);
+            window.blist[bid].bicon_url = url;
         }
         window.buddy_list.onChange(window.blist);
     },
@@ -59,6 +63,12 @@ var Dispatcher = {
             window.conversations[bid].type_state = params.state;
         }
         // TODO: repaint conversations window
+    },
+    handle_session_message: function(method, params) {
+        console.log("session:", method, params);
+        if (method == "set_session") {
+            window.session_id = params["session_id"];
+        }
     }
 };
 
index 3719aa530d95558f41d0c228ab31995dc9fc2559..a384b589c7cdb8aed78a011f5018b081a7e4a094 100644 (file)
@@ -1,6 +1,7 @@
 import json
 import logging
 import os
+import shutil
 import socket
 import struct
 import subprocess
@@ -12,6 +13,11 @@ import tornado.websocket
 
 pwd = os.path.dirname(os.path.abspath(__file__))
 
+_SESSION_BYTES = 8
+
+# path to the ribbon executable
+ribbon_binary = os.path.join(os.path.dirname(pwd), "ribbon", "ribbon")
+
 logging.basicConfig(
         level=logging.DEBUG,
         format='%(asctime)s : %(levelname)s : %(name)s : %(message)s',
@@ -54,36 +60,52 @@ class WSHandler(tornado.websocket.WebSocketHandler):
             self.dispatch_backlog()
 
     def open(self):
-        # Create a new connection to ribbon.
+        # Create a new ribbon subprocess, then connect to it.
+        self.sess_id = os.urandom(_SESSION_BYTES).encode('hex')
+        self.state_dir = os.path.join(pwd, "state", self.sess_id)
+        self.ribbon_subprocess = subprocess.Popen( [ribbon_binary, "--state-dir", self.state_dir], close_fds=True )
+
+        # TODO: find a better way to make this work, like exponential backoff
+        # polling for the socket that's supposed to appear
+        # For now, a one-second delay gives ribbon enough time to start up
+        import time
+        time.sleep(1.0)
+
         self.ribbon_ready = False
         self.backlog = [] # A list of bytestrings queued to be sent on the socket.
         self.ribbon_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
         self.ribbon_stream = tornado.iostream.IOStream(self.ribbon_socket)
-        self.ribbon_stream.connect( os.path.join(pwd, "state", "socket"), self.on_ribbon_ready)
+        self.ribbon_stream.connect(os.path.join(self.state_dir, "socket"), self.on_ribbon_ready)
         log.info('new connection')
-        self.write_message('{"key":"value"}')
+        m = { "sender": "session",
+              "method": "set_session",
+              "params": {"session_id": self.sess_id },
+              }
+        self.write_message(json.dumps(m))
     def on_message(self, message):
         log.info('message received: %r', message)
         data = json.loads(message)
         self.queue_message(message.encode("latin1"))
 
     def on_close(self):
-        log.info('connection closed')
-
+        log.info('connection closed: {}'.format(self.session_id))
+        # kill child ribbon
+        self.ribbon_subprocess.kill()
+        self.ribbon_subprocess.wait()
+        # clean up that ribbon instance's work directory
+        shutil.rmtree(self.state_dir)
 
 application = tornado.web.Application([
     (r'/(index.html)', tornado.web.StaticFileHandler, {'path': pwd}),
     (r'/([a-z]*\.js)', tornado.web.StaticFileHandler, {'path': pwd}),
     (r'/([a-z]*\.css)', tornado.web.StaticFileHandler, {'path': pwd}),
-    (r'/icons/(.*)', tornado.web.StaticFileHandler, {'path': os.path.join(pwd, 'state', 'icons')}),
+    # mildly janky url mapping
+    (r'/icons/([0-9a-f]{16}/icons/.*)', tornado.web.StaticFileHandler, {'path': os.path.join(pwd, 'state')}),
     (r'/ws', WSHandler),
 ])
 
 
 if __name__ == "__main__":
-    # Spawn the ribbon subprocess
-    ribbon_binary = os.path.join(os.path.dirname(pwd), "ribbon", "ribbon")
-    ribbon = subprocess.Popen( [ribbon_binary, "--state-dir", os.path.join(pwd, "state")], close_fds=True )
 
     # Spawn the http server
     http_server = tornado.httpserver.HTTPServer(application)