This is an automated email from the ASF dual-hosted git repository.

rubys pushed a commit to branch master
in repository https://git-dual.apache.org/repos/asf/whimsy.git

The following commit(s) were added to refs/heads/master by this push:
       new  496a90e   refactor out socket tracking logic to a separate class
496a90e is described below

commit 496a90ef62b0aff531443512601c789f7130fa95
Author: Sam Ruby <ru...@intertwingly.net>
AuthorDate: Thu Oct 13 11:34:25 2016 -0400

    refactor out socket tracking logic to a separate class
---
 www/board/agenda/daemon/channel.rb | 69 ++++++++++++++++++++++++++++++++++++++
 www/board/agenda/daemon/wss.rb     | 28 ++++------------
 2 files changed, 75 insertions(+), 22 deletions(-)

diff --git a/www/board/agenda/daemon/channel.rb 
b/www/board/agenda/daemon/channel.rb
new file mode 100644
index 0000000..0a5b967
--- /dev/null
+++ b/www/board/agenda/daemon/channel.rb
@@ -0,0 +1,69 @@
+#
+# Maintain two lists of active sockets (channels): one associating a user
+# with a list of sockets, and one associating each socket to a single user.
+#
+
+require 'json'
+require 'concurrent'
+
+class Channel
+  @@sockets = Concurrent::Map.new
+  @@users = Concurrent::Map.new {|map,key| map[key]=[]}
+
+  # add a new socket/userid pair
+  def self.add(ws, id)
+    if @@users[id].empty?
+      self.post_all(type: :arrive, user: id, present: self.present,
+        timestamp: Time.now.to_f*1000)
+    end
+    @@users[id] << ws
+    @@sockets[ws] = id
+  end
+
+  # send a message to a list of clients
+  def self.post(clients, msg)
+    clients.each do |client|
+      EM.defer(
+        ->() {client.send msg},
+        ->(response) {},
+        ->(error) {client.close rescue nil}
+      )
+    end
+  end
+
+  # send a message to all users
+  def self.post_all(msg)
+    msg = JSON.dump(msg) if msg.instance_of? Hash
+    self.post @@sockets.keys, msg
+  end
+
+  # send a message to a specific user
+  def self.post_private(user, msg)
+    self.post @@users[user] || [], msg
+  end
+
+  # delete a socket connection
+  def self.delete(ws)
+    id = @@sockets.delete(ws)
+    if id
+      @@users[id].delete ws
+      if @@users[id].empty?
+        @@users.delete id 
+        self.post_all(type: :depart, user: id, present: self.present,
+          timestamp: Time.now.to_f*1000)
+      end
+    end
+  end
+
+  # return a list of active users
+  def self.present
+    @@users.keys
+  end
+
+  # close all open sockets
+  def self.close_all
+    @@sockets.keys.each do |client|
+      client.close
+    end
+  end
+end
diff --git a/www/board/agenda/daemon/wss.rb b/www/board/agenda/daemon/wss.rb
index a4d5136..3fb82a7 100755
--- a/www/board/agenda/daemon/wss.rb
+++ b/www/board/agenda/daemon/wss.rb
@@ -9,9 +9,7 @@ require 'rbconfig'
 require 'json'
 
 require_relative './session'
-
-users = Hash.new {|hash, key| hash[key] = []}
-sessions = {}
+require_relative './channel'
 
 ########################################################################
 #                         Parse argument list                          #
@@ -89,9 +87,7 @@ listener.start
 ########################################################################
 
 at_exit do
-  sessions.keys.each do |client|
-    client.close
-  end
+  Channel.close_all
 end
 
 ########################################################################
@@ -111,8 +107,7 @@ end
 EM.run do
   WebSocket::EventMachine::Server.start(server_options) do |ws|
     ws.onclose do 
-      id = sessions.delete(ws)
-      users[id].delete ws if id
+      Channel.delete ws
     end
 
     ws.onmessage do |msg|
@@ -123,8 +118,7 @@ EM.run do
       if headers['session']
         session = Session[headers['session']]
         if session
-          users[session[:id]] << ws
-          sessions[ws] = session[:id]
+          Channel.add ws, session[:id]
           ws.send JSON.dump(session.merge type: 'login')
         end
       end
@@ -132,19 +126,9 @@ EM.run do
       # forward message
       unless msg.empty?
         if headers['private']
-          # send only to a specific user
-          clients = users[headers['private']] || []
+          Channel.post_private headers['private'], msg
         else
-          # send to all users
-          clients = sessions.keys
-        end
-
-        clients.each do |client|
-          EM.defer(
-            ->() {client.send msg},
-            ->(response) {},
-            ->(error) {client.close rescue nil}
-          )
+          Channel.post_all msg
         end
       end
     end

-- 
To stop receiving notification emails like this one, please contact
['"commits@whimsical.apache.org" <commits@whimsical.apache.org>'].

Reply via email to