aboutsummaryrefslogtreecommitdiffstats
path: root/lib/assets/javascripts/cable/connection_monitor.js.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'lib/assets/javascripts/cable/connection_monitor.js.coffee')
-rw-r--r--lib/assets/javascripts/cable/connection_monitor.js.coffee65
1 files changed, 65 insertions, 0 deletions
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..fc5093c5eb
--- /dev/null
+++ b/lib/assets/javascripts/cable/connection_monitor.js.coffee
@@ -0,0 +1,65 @@
+class Cable.ConnectionMonitor
+ identifier: Cable.PING_IDENTIFIER
+
+ pollInterval:
+ min: 2
+ max: 30
+
+ staleThreshold:
+ startedAt: 4
+ pingedAt: 8
+
+ constructor: (@consumer) ->
+ @consumer.subscribers.add(this)
+ @start()
+
+ connected: ->
+ @reset()
+ @pingedAt = now()
+
+ received: ->
+ @pingedAt = now()
+
+ reset: ->
+ @reconnectAttempts = 0
+
+ start: ->
+ @reset()
+ delete @stoppedAt
+ @startedAt = now()
+ @poll()
+
+ stop: ->
+ @stoppedAt = now()
+
+ poll: ->
+ setTimeout =>
+ unless @stoppedAt
+ @reconnectIfStale()
+ @poll()
+ , @getInterval()
+
+ getInterval: ->
+ {min, max} = @pollInterval
+ interval = 4 * Math.log(@reconnectAttempts + 1)
+ clamp(interval, min, max) * 1000
+
+ reconnectIfStale: ->
+ if @connectionIsStale()
+ @reconnectAttempts += 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))