From 336d12f97aba485809005f27d4952705e312251c Mon Sep 17 00:00:00 2001 From: Javan Makhmali Date: Sat, 27 Jun 2015 16:17:00 -0400 Subject: Rework connection monitor --- lib/assets/javascripts/cable/connection.js.coffee | 3 -- .../javascripts/cable/connection_monitor.js.coffee | 62 +++++++++++++++------- lib/assets/javascripts/cable/consumer.js.coffee | 2 + .../javascripts/cable/subscriber_manager.js.coffee | 6 ++- 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/lib/assets/javascripts/cable/connection.js.coffee b/lib/assets/javascripts/cable/connection.js.coffee index 98af9ad8ab..4f7d2abada 100644 --- a/lib/assets/javascripts/cable/connection.js.coffee +++ b/lib/assets/javascripts/cable/connection.js.coffee @@ -1,8 +1,5 @@ -#= require cable/connection_monitor - class Cable.Connection constructor: (@consumer) -> - new Cable.ConnectionMonitor @consumer @open() send: (data) -> diff --git a/lib/assets/javascripts/cable/connection_monitor.js.coffee b/lib/assets/javascripts/cable/connection_monitor.js.coffee index bb4ee8f7f6..fc5093c5eb 100644 --- a/lib/assets/javascripts/cable/connection_monitor.js.coffee +++ b/lib/assets/javascripts/cable/connection_monitor.js.coffee @@ -1,13 +1,17 @@ class Cable.ConnectionMonitor - MAX_CONNECTION_INTERVAL: 5 * 1000 - PING_STALE_INTERVAL: 8 * 1000 - identifier: Cable.PING_IDENTIFIER + pollInterval: + min: 2 + max: 30 + + staleThreshold: + startedAt: 4 + pingedAt: 8 + constructor: (@consumer) -> - @reset() @consumer.subscribers.add(this) - @pollConnection() + @start() connected: -> @reset() @@ -17,25 +21,45 @@ class Cable.ConnectionMonitor @pingedAt = now() reset: -> - @connectionAttempts = 1 + @reconnectAttempts = 0 + + start: -> + @reset() + delete @stoppedAt + @startedAt = now() + @poll() - pollConnection: -> + stop: -> + @stoppedAt = now() + + poll: -> setTimeout => - @reconnect() if @connectionIsStale() - @pollConnection() - , @getPollTimeout() + unless @stoppedAt + @reconnectIfStale() + @poll() + , @getInterval() - getPollTimeout: -> - interval = (Math.pow(2, @connectionAttempts) - 1) * 1000 - if interval > @MAX_CONNECTION_INTERVAL then @MAX_CONNECTION_INTERVAL else interval + getInterval: -> + {min, max} = @pollInterval + interval = 4 * Math.log(@reconnectAttempts + 1) + clamp(interval, min, max) * 1000 - connectionIsStale: -> - @pingedAt? and (now() - @pingedAt) > @PING_STALE_INTERVAL + reconnectIfStale: -> + if @connectionIsStale() + @reconnectAttempts += 1 + @consumer.connection.reopen() - reconnect: -> - console.log "Ping took too long to arrive. Reconnecting.." - @connectionAttempts += 1 - @consumer.connection.reopen() + connectionIsStale: -> + if @pingedAt + secondsSince(@pingedAt) > @staleThreshold.pingedAt + else + secondsSince(@startedAt) > @staleThreshold.startedAt now = -> new Date().getTime() + + secondsSince = (time) -> + (now() - time) / 1000 + + clamp = (number, min, max) -> + Math.max(min, Math.min(max, number)) diff --git a/lib/assets/javascripts/cable/consumer.js.coffee b/lib/assets/javascripts/cable/consumer.js.coffee index a9abd6256a..b9c08807f2 100644 --- a/lib/assets/javascripts/cable/consumer.js.coffee +++ b/lib/assets/javascripts/cable/consumer.js.coffee @@ -1,4 +1,5 @@ #= require cable/connection +#= require cable/connection_monitor #= require cable/subscription #= require cable/subscriber_manager @@ -6,6 +7,7 @@ class Cable.Consumer constructor: (@url) -> @subscribers = new Cable.SubscriberManager this @connection = new Cable.Connection this + @connectionMonitor = new Cable.ConnectionMonitor this createSubscription: (channelName, mixin) -> channel = channelName diff --git a/lib/assets/javascripts/cable/subscriber_manager.js.coffee b/lib/assets/javascripts/cable/subscriber_manager.js.coffee index 922c74808c..0b6a16590c 100644 --- a/lib/assets/javascripts/cable/subscriber_manager.js.coffee +++ b/lib/assets/javascripts/cable/subscriber_manager.js.coffee @@ -32,5 +32,7 @@ class Cable.SubscriberManager sendCommand: (subscriber, command) -> {identifier} = subscriber - return true if identifier is Cable.PING_IDENTIFIER - @consumer.send({command, identifier}) + if identifier is Cable.PING_IDENTIFIER + @consumer.connection.isOpen() + else + @consumer.send({command, identifier}) -- cgit v1.2.3