From c846f43d46908750020710b4e9437f9395fb9594 Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Thu, 25 Jun 2015 13:52:47 -0400 Subject: Extract connection monitoring and rewrite as a subscriber --- lib/assets/javascripts/cable/connection.js.coffee | 94 +++++----------------- .../javascripts/cable/connection_monitor.js.coffee | 41 ++++++++++ .../javascripts/cable/subscriber_manager.js.coffee | 1 + 3 files changed, 64 insertions(+), 72 deletions(-) create mode 100644 lib/assets/javascripts/cable/connection_monitor.js.coffee (limited to 'lib/assets/javascripts/cable') diff --git a/lib/assets/javascripts/cable/connection.js.coffee b/lib/assets/javascripts/cable/connection.js.coffee index e987c227c6..096dd519f7 100644 --- a/lib/assets/javascripts/cable/connection.js.coffee +++ b/lib/assets/javascripts/cable/connection.js.coffee @@ -1,10 +1,8 @@ -class Cable.Connection - MAX_CONNECTION_INTERVAL: 5 * 1000 - PING_STALE_INTERVAL: 8 +#= require cable/connection_monitor +class Cable.Connection constructor: (@cable) -> - @resetPingTime() - @resetConnectionAttemptsCount() + new Cable.ConnectionMonitor @cable @connect() send: (data) -> @@ -15,88 +13,40 @@ class Cable.Connection false connect: -> - @websocket = @createWebSocket() + @removeWebsocket() + @createWebSocket() createWebSocket: -> - ws = new WebSocket(@cable.url) - ws.onmessage = @onMessage - ws.onopen = @onConnect - ws.onclose = @onClose - ws.onerror = @onError - ws + @websocket = new WebSocket(@cable.url) + @websocket.onmessage = @onMessage + @websocket.onopen = @onConnect + @websocket.onclose = @onClose + @websocket.onerror = @onError + @websocket + + removeWebsocket: -> + if @websocket? + @websocket.onclose = -> # no-op + @websocket.onerror = -> # no-op + @websocket.close() + @websocket = null onMessage: (message) => data = JSON.parse message.data - - if data.identifier is '_ping' - @pingReceived(data.message) - else - @cable.subscribers.notify(data.identifier, "received", data.message) + @cable.subscribers.notify(data.identifier, "received", data.message) onConnect: => - @startWaitingForPing() - @resetConnectionAttemptsCount() @cable.subscribers.reload() onClose: => - @reconnect() + @disconnect() onError: => - @reconnect() + @disconnect() isConnected: -> @websocket?.readyState is 1 disconnect: -> - @removeExistingConnection() - @resetPingTime() @cable.subscribers.notifyAll("disconnected") - - reconnect: -> - @disconnect() - - setTimeout => - @incrementConnectionAttemptsCount() - @connect() - , @generateReconnectInterval() - - removeExistingConnection: -> - if @websocket? - @clearPingWaitTimeout() - - @websocket.onclose = -> # no-op - @websocket.onerror = -> # no-op - @websocket.close() - @websocket = null - - resetConnectionAttemptsCount: -> - @connectionAttempts = 1 - - incrementConnectionAttemptsCount: -> - @connectionAttempts += 1 - - generateReconnectInterval: () -> - interval = (Math.pow(2, @connectionAttempts) - 1) * 1000 - if interval > @MAX_CONNECTION_INTERVAL then @MAX_CONNECTION_INTERVAL else interval - - startWaitingForPing: -> - @clearPingWaitTimeout() - - @waitForPingTimeout = setTimeout => - console.log "Ping took too long to arrive. Reconnecting.." - @reconnect() - , @PING_STALE_INTERVAL * 1000 - - clearPingWaitTimeout: -> - clearTimeout(@waitForPingTimeout) - - resetPingTime: -> - @lastPingTime = null - - pingReceived: (timestamp) -> - if @lastPingTime? and (timestamp - @lastPingTime) > @PING_STALE_INTERVAL - console.log "Websocket connection is stale. Reconnecting.." - @reconnect() - else - @startWaitingForPing() - @lastPingTime = timestamp + @removeWebsocket() diff --git a/lib/assets/javascripts/cable/connection_monitor.js.coffee b/lib/assets/javascripts/cable/connection_monitor.js.coffee new file mode 100644 index 0000000000..078e1d3b26 --- /dev/null +++ b/lib/assets/javascripts/cable/connection_monitor.js.coffee @@ -0,0 +1,41 @@ +class Cable.ConnectionMonitor + MAX_CONNECTION_INTERVAL: 5 * 1000 + PING_STALE_INTERVAL: 8 * 1000 + + identifier: Cable.PING_IDENTIFIER + + constructor: (@cable) -> + @reset() + @cable.subscribers.add(this) + @pollConnection() + + connected: -> + @reset() + @pingedAt = now() + + received: -> + @pingedAt = now() + + reset: -> + @connectionAttempts = 1 + + pollConnection: -> + setTimeout => + @reconnect() if @connectionIsStale() + @pollConnection() + , @getPollTimeout() + + getPollTimeout: -> + interval = (Math.pow(2, @connectionAttempts) - 1) * 1000 + if interval > @MAX_CONNECTION_INTERVAL then @MAX_CONNECTION_INTERVAL else interval + + connectionIsStale: -> + @pingedAt? and (now() - @pingedAt) > @PING_STALE_INTERVAL + + reconnect: -> + console.log "Ping took too long to arrive. Reconnecting.." + @connectionAttempts += 1 + @cable.connection.connect() + + now = -> + new Date().getTime() diff --git a/lib/assets/javascripts/cable/subscriber_manager.js.coffee b/lib/assets/javascripts/cable/subscriber_manager.js.coffee index e2e6c9e228..d76832a802 100644 --- a/lib/assets/javascripts/cable/subscriber_manager.js.coffee +++ b/lib/assets/javascripts/cable/subscriber_manager.js.coffee @@ -30,4 +30,5 @@ class Cable.SubscriberManager subscriber[event]?(args...) sendCommand: (command, identifier) -> + return true if identifier is Cable.PING_IDENTIFIER @cable.send({command, identifier}) -- cgit v1.2.3