diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2015-09-02 03:00:21 -0300 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2015-09-02 03:00:21 -0300 |
commit | 4bfe1ab907e438c9d35a13d1a342acb96c7dd1f0 (patch) | |
tree | 7f5b9afd7a6326161c75270701f1e880e4f20263 /lib/assets/javascripts/cable/connection_monitor.coffee | |
parent | 0cf1db6be29fb2269d722bedd690641e0f949b36 (diff) | |
parent | eb8c713c987480e7a0362ae3de617ba0c0f27d7f (diff) | |
download | rails-4bfe1ab907e438c9d35a13d1a342acb96c7dd1f0.tar.gz rails-4bfe1ab907e438c9d35a13d1a342acb96c7dd1f0.tar.bz2 rails-4bfe1ab907e438c9d35a13d1a342acb96c7dd1f0.zip |
Merge pull request #71 from rails/coffee-only
.js.coffee -> .coffee
Diffstat (limited to 'lib/assets/javascripts/cable/connection_monitor.coffee')
-rw-r--r-- | lib/assets/javascripts/cable/connection_monitor.coffee | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/assets/javascripts/cable/connection_monitor.coffee b/lib/assets/javascripts/cable/connection_monitor.coffee new file mode 100644 index 0000000000..30ce11957c --- /dev/null +++ b/lib/assets/javascripts/cable/connection_monitor.coffee @@ -0,0 +1,87 @@ +# Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting +# revival reconnections if things go astray. Internal class, not intended for direct user manipulation. +class Cable.ConnectionMonitor + identifier: Cable.PING_IDENTIFIER + + pollInterval: + min: 2 + max: 30 + + staleThreshold: + startedAt: 4 + pingedAt: 8 + + constructor: (@consumer) -> + @consumer.subscriptions.add(this) + @start() + + connected: -> + @reset() + @pingedAt = now() + + disconnected: -> + if @reconnectAttempts++ is 0 + setTimeout => + @consumer.connection.open() unless @consumer.connection.isOpen() + , 200 + + received: -> + @pingedAt = now() + + reset: -> + @reconnectAttempts = 0 + + start: -> + @reset() + delete @stoppedAt + @startedAt = now() + @poll() + document.addEventListener("visibilitychange", @visibilityDidChange) + + stop: -> + @stoppedAt = now() + document.removeEventListener("visibilitychange", @visibilityDidChange) + + 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++ + @consumer.connection.reopen() + + connectionIsStale: -> + if @pingedAt + secondsSince(@pingedAt) > @staleThreshold.pingedAt + else + secondsSince(@startedAt) > @staleThreshold.startedAt + + visibilityDidChange: => + if document.visibilityState is "visible" + setTimeout => + if @connectionIsStale() or not @consumer.connection.isOpen() + @consumer.connection.reopen() + , 200 + + toJSON: -> + interval = @getInterval() + connectionIsStale = @connectionIsStale() + {@startedAt, @stoppedAt, @pingedAt, @reconnectAttempts, connectionIsStale, interval} + + now = -> + new Date().getTime() + + secondsSince = (time) -> + (now() - time) / 1000 + + clamp = (number, min, max) -> + Math.max(min, Math.min(max, number)) |