Skip to content

Commit

Permalink
Immediately remove closed websocket clients from weakset
Browse files Browse the repository at this point in the history
When a client closes the connection, immediately remove the WebSocket
instance from the instances list, rather than waiting for the heartbeat
to time the connection out and garbage collect it.

This is a small optimisation to ensure that the stats on number of
connected clients are as accurate as possible, and that we don't waste
CPU time iterating over sockets that are terminated.
  • Loading branch information
nickstenning committed Feb 23, 2016
1 parent 64e720e commit a3d21d4
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
23 changes: 23 additions & 0 deletions h/streamer/test/websocket_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,29 @@
FakeMessage = namedtuple('FakeMessage', ['data'])


def test_websocket_stores_instance_list():
socket = mock.Mock()
clients = [websocket.WebSocket(socket), websocket.WebSocket(socket)]

for c in clients:
assert c in websocket.WebSocket.instances


def test_websocket_removes_self_from_instance_list_when_closed():
socket = mock.Mock()
client1 = websocket.WebSocket(socket)
client2 = websocket.WebSocket(socket)

assert len(websocket.WebSocket.instances) == 2
client1.closed(1000)
assert client1 not in websocket.WebSocket.instances
client2.closed(1000)
assert client2 not in websocket.WebSocket.instances

# A second closure (however unusual) should not raise
client1.closed(1000)


def test_socket_enqueues_incoming_messages():
queue = Queue()
request = testing.DummyRequest()
Expand Down
6 changes: 6 additions & 0 deletions h/streamer/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ def received_message(self, msg):
log.warn('Streamer work queue full! Unable to queue message from '
'WebSocket client having waited 0.1s: giving up.')

def closed(self, code, reason=None):
try:
self.instances.remove(self)
except KeyError:
pass


def handle_message(message):
socket = message.socket
Expand Down

0 comments on commit a3d21d4

Please sign in to comment.