Brian Gough 7 лет назад
Родитель
Сommit
92e6910180

+ 6 - 4
services/real-time/app/coffee/ChannelManager.coffee

@@ -9,11 +9,13 @@ ClientMap = new Map() # for each redis client, stores a Set of subscribed channe
 # handled by RoomManager.
 
 module.exports = ChannelManager =
-    _createNewClientEntry: (rclient) ->
-        ClientMap.set(rclient, new Set()).get(rclient)
+    getClientMapEntry: (rclient) ->
+        # return the rclient channel set if it exists, otherwise create and
+        # return an empty set for the client.
+        ClientMap.get(rclient) || ClientMap.set(rclient, new Set()).get(rclient)
 
     subscribe: (rclient, baseChannel, id) ->
-        existingChannelSet = ClientMap.get(rclient) || @_createNewClientEntry(rclient)
+        existingChannelSet = @getClientMapEntry(rclient)
         channel = "#{baseChannel}:#{id}"
         if existingChannelSet.has(channel)
             logger.error {channel}, "already subscribed - shouldn't happen"
@@ -24,7 +26,7 @@ module.exports = ChannelManager =
             metrics.inc "subscribe.#{baseChannel}"
 
     unsubscribe: (rclient, baseChannel, id) ->
-        existingChannelSet = ClientMap.get(rclient)
+        existingChannelSet = @getClientMapEntry(rclient)
         channel = "#{baseChannel}:#{id}"
         if !existingChannelSet.has(channel)
             logger.error {channel}, "not subscribed - shouldn't happen"

+ 25 - 22
services/real-time/app/coffee/RoomManager.coffee

@@ -17,13 +17,13 @@ RoomEvents = new EventEmitter()
 module.exports = RoomManager =
 
     joinProject: (client, project_id) ->
-        @_join client, "project", project_id
+        @joinEntity client, "project", project_id
 
     joinDoc: (client, doc_id) ->
-        @_join client, "doc", doc_id
+        @joinEntity client, "doc", doc_id
 
     leaveDoc: (client, doc_id) ->
-        @_leave client, "doc", doc_id
+        @leaveEntity client, "doc", doc_id
 
     leaveProjectAndDocs: (client) ->
         # what rooms is this client in? we need to leave them all. socket.io
@@ -33,27 +33,12 @@ module.exports = RoomManager =
         # has not joined any rooms and do a final disconnection.
         for id in @_roomsClientIsIn(client)
             entity = IdMap.get(id)
-            @_leave client, entity, id
+            @leaveEntity client, entity, id
 
     eventSource: () ->
         return RoomEvents
 
-    # internal functions below, these access socket.io rooms data directly and
-    # will need updating for socket.io v2
-
-    _clientsInRoom: (client, room) ->
-        nsp = client.namespace.name
-        name = (nsp + '/') + room;
-        return (client.manager?.rooms?[name] || []).length
-
-    _roomsClientIsIn: (client) ->
-        roomList = for fullRoomPath of client.manager.roomClients?[client.id] when fullRoomPath isnt ''
-            # strip socket.io prefix from room to get original id
-            [prefix, room] = fullRoomPath.split('/', 2)
-            room
-        return roomList
-
-    _join: (client, entity, id) ->
+    joinEntity: (client, entity, id) ->
         beforeCount = @_clientsInRoom(client, id)
         client.join id
         afterCount = @_clientsInRoom(client, id)
@@ -64,13 +49,31 @@ module.exports = RoomManager =
             RoomEvents.emit "#{entity}-active", id
             IdMap.set(id, entity)
 
-    _leave: (client, entity, id) ->
+    leaveEntity: (client, entity, id) ->
         beforeCount = @_clientsInRoom(client, id)
         client.leave id
         afterCount = @_clientsInRoom(client, id)
         logger.log {client: client.id, entity, id, beforeCount, afterCount}, "client left room"
         # is the room now empty? if so, unsubscribe
+        if !entity?
+            logger.error {entity: id}, "unknown entity when leaving with id"
+            return
         if beforeCount == 1 and afterCount == 0
             logger.log {entity, id}, "room is now empty"
             RoomEvents.emit "#{entity}-empty", id
-            IdMap.delete(id)
+            IdMap.delete(id)
+
+    # internal functions below, these access socket.io rooms data directly and
+    # will need updating for socket.io v2
+
+    _clientsInRoom: (client, room) ->
+        nsp = client.namespace.name
+        name = (nsp + '/') + room;
+        return (client.manager?.rooms?[name] || []).length
+
+    _roomsClientIsIn: (client) ->
+        roomList = for fullRoomPath of client.manager.roomClients?[client.id] when fullRoomPath isnt ''
+            # strip socket.io prefix from room to get original id
+            [prefix, room] = fullRoomPath.split('/', 2)
+            room
+        return roomList