mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Defer starting connection monitor until a connection is opened
This commit is contained in:
parent
8e9a1a62d3
commit
96e6de9552
3 changed files with 56 additions and 45 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
#= require ./connection_monitor
|
||||||
|
|
||||||
# Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
|
# Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
|
||||||
|
|
||||||
{message_types} = ActionCable.INTERNAL
|
{message_types} = ActionCable.INTERNAL
|
||||||
|
@ -6,6 +8,7 @@ class ActionCable.Connection
|
||||||
@reopenDelay: 500
|
@reopenDelay: 500
|
||||||
|
|
||||||
constructor: (@consumer) ->
|
constructor: (@consumer) ->
|
||||||
|
@monitor = new ActionCable.ConnectionMonitor this
|
||||||
|
|
||||||
send: (data) ->
|
send: (data) ->
|
||||||
if @isOpen()
|
if @isOpen()
|
||||||
|
@ -23,6 +26,7 @@ class ActionCable.Connection
|
||||||
@uninstallEventHandlers() if @webSocket?
|
@uninstallEventHandlers() if @webSocket?
|
||||||
@webSocket = new WebSocket(@consumer.url)
|
@webSocket = new WebSocket(@consumer.url)
|
||||||
@installEventHandlers()
|
@installEventHandlers()
|
||||||
|
@monitor.start()
|
||||||
true
|
true
|
||||||
|
|
||||||
close: ->
|
close: ->
|
||||||
|
@ -72,9 +76,9 @@ class ActionCable.Connection
|
||||||
{identifier, message, type} = JSON.parse(event.data)
|
{identifier, message, type} = JSON.parse(event.data)
|
||||||
switch type
|
switch type
|
||||||
when message_types.welcome
|
when message_types.welcome
|
||||||
@consumer.connectionMonitor.connected()
|
@monitor.recordConnect()
|
||||||
when message_types.ping
|
when message_types.ping
|
||||||
@consumer.connectionMonitor.ping()
|
@monitor.recordPing()
|
||||||
when message_types.confirmation
|
when message_types.confirmation
|
||||||
@consumer.subscriptions.notify(identifier, "connected")
|
@consumer.subscriptions.notify(identifier, "connected")
|
||||||
when message_types.rejection
|
when message_types.rejection
|
||||||
|
@ -98,5 +102,5 @@ class ActionCable.Connection
|
||||||
disconnect: ->
|
disconnect: ->
|
||||||
return if @disconnected
|
return if @disconnected
|
||||||
@disconnected = true
|
@disconnected = true
|
||||||
@consumer.connectionMonitor.disconnected()
|
|
||||||
@consumer.subscriptions.notifyAll("disconnected")
|
@consumer.subscriptions.notifyAll("disconnected")
|
||||||
|
@monitor.recordDisconnect()
|
||||||
|
|
|
@ -7,60 +7,69 @@ class ActionCable.ConnectionMonitor
|
||||||
|
|
||||||
@staleThreshold: 6 # Server::Connections::BEAT_INTERVAL * 2 (missed two pings)
|
@staleThreshold: 6 # Server::Connections::BEAT_INTERVAL * 2 (missed two pings)
|
||||||
|
|
||||||
constructor: (@consumer) ->
|
constructor: (@connection) ->
|
||||||
@start()
|
|
||||||
|
|
||||||
connected: ->
|
|
||||||
@reset()
|
|
||||||
@pingedAt = now()
|
|
||||||
delete @disconnectedAt
|
|
||||||
ActionCable.log("ConnectionMonitor connected")
|
|
||||||
|
|
||||||
disconnected: ->
|
|
||||||
@disconnectedAt = now()
|
|
||||||
ActionCable.log("ConnectionMonitor disconnected")
|
|
||||||
|
|
||||||
ping: ->
|
|
||||||
@pingedAt = now()
|
|
||||||
|
|
||||||
reset: ->
|
|
||||||
@reconnectAttempts = 0
|
@reconnectAttempts = 0
|
||||||
@consumer.connection.isOpen()
|
|
||||||
|
|
||||||
start: ->
|
start: ->
|
||||||
@reset()
|
unless @isRunning()
|
||||||
delete @stoppedAt
|
@startedAt = now()
|
||||||
@startedAt = now()
|
delete @stoppedAt
|
||||||
@poll()
|
@startPolling()
|
||||||
document.addEventListener("visibilitychange", @visibilityDidChange)
|
document.addEventListener("visibilitychange", @visibilityDidChange)
|
||||||
ActionCable.log("ConnectionMonitor started, pollInterval is #{@getInterval()}ms")
|
ActionCable.log("ConnectionMonitor started. pollInterval = #{@getPollInterval()} ms")
|
||||||
|
|
||||||
stop: ->
|
stop: ->
|
||||||
@stoppedAt = now()
|
if @isRunning()
|
||||||
document.removeEventListener("visibilitychange", @visibilityDidChange)
|
@stoppedAt = now()
|
||||||
ActionCable.log("ConnectionMonitor stopped")
|
@stopPolling()
|
||||||
|
document.removeEventListener("visibilitychange", @visibilityDidChange)
|
||||||
|
ActionCable.log("ConnectionMonitor stopped")
|
||||||
|
|
||||||
|
isRunning: ->
|
||||||
|
@startedAt? and not @stoppedAt?
|
||||||
|
|
||||||
|
recordPing: ->
|
||||||
|
@pingedAt = now()
|
||||||
|
|
||||||
|
recordConnect: ->
|
||||||
|
@reconnectAttempts = 0
|
||||||
|
@recordPing()
|
||||||
|
delete @disconnectedAt
|
||||||
|
ActionCable.log("ConnectionMonitor recorded connect")
|
||||||
|
|
||||||
|
recordDisconnect: ->
|
||||||
|
@disconnectedAt = now()
|
||||||
|
ActionCable.log("ConnectionMonitor recorded disconnect")
|
||||||
|
|
||||||
|
# Private
|
||||||
|
|
||||||
|
startPolling: ->
|
||||||
|
@stopPolling()
|
||||||
|
@poll()
|
||||||
|
|
||||||
|
stopPolling: ->
|
||||||
|
clearTimeout(@pollTimeout)
|
||||||
|
|
||||||
poll: ->
|
poll: ->
|
||||||
setTimeout =>
|
@pollTimeout = setTimeout =>
|
||||||
unless @stoppedAt
|
@reconnectIfStale()
|
||||||
@reconnectIfStale()
|
@poll()
|
||||||
@poll()
|
, @getPollInterval()
|
||||||
, @getInterval()
|
|
||||||
|
|
||||||
getInterval: ->
|
getPollInterval: ->
|
||||||
{min, max} = @constructor.pollInterval
|
{min, max} = @constructor.pollInterval
|
||||||
interval = 5 * Math.log(@reconnectAttempts + 1)
|
interval = 5 * Math.log(@reconnectAttempts + 1)
|
||||||
clamp(interval, min, max) * 1000
|
Math.round(clamp(interval, min, max) * 1000)
|
||||||
|
|
||||||
reconnectIfStale: ->
|
reconnectIfStale: ->
|
||||||
if @connectionIsStale()
|
if @connectionIsStale()
|
||||||
ActionCable.log("ConnectionMonitor detected stale connection, reconnectAttempts = #{@reconnectAttempts}")
|
ActionCable.log("ConnectionMonitor detected stale connection. reconnectAttempts = #{@reconnectAttempts}, pollInterval = #{@getPollInterval()} ms, time disconnected = #{secondsSince(@disconnectedAt)} s, stale threshold = #{@constructor.staleThreshold} s")
|
||||||
@reconnectAttempts++
|
@reconnectAttempts++
|
||||||
if @disconnectedRecently()
|
if @disconnectedRecently()
|
||||||
ActionCable.log("ConnectionMonitor skipping reopen because recently disconnected at #{@disconnectedAt}")
|
ActionCable.log("ConnectionMonitor skipping reopening recent disconnect")
|
||||||
else
|
else
|
||||||
ActionCable.log("ConnectionMonitor reopening")
|
ActionCable.log("ConnectionMonitor reopening")
|
||||||
@consumer.connection.reopen()
|
@connection.reopen()
|
||||||
|
|
||||||
connectionIsStale: ->
|
connectionIsStale: ->
|
||||||
secondsSince(@pingedAt ? @startedAt) > @constructor.staleThreshold
|
secondsSince(@pingedAt ? @startedAt) > @constructor.staleThreshold
|
||||||
|
@ -71,9 +80,9 @@ class ActionCable.ConnectionMonitor
|
||||||
visibilityDidChange: =>
|
visibilityDidChange: =>
|
||||||
if document.visibilityState is "visible"
|
if document.visibilityState is "visible"
|
||||||
setTimeout =>
|
setTimeout =>
|
||||||
if @connectionIsStale() or not @consumer.connection.isOpen()
|
if @connectionIsStale() or not @connection.isOpen()
|
||||||
ActionCable.log("ConnectionMonitor reopening stale connection after visibilitychange to #{document.visibilityState}")
|
ActionCable.log("ConnectionMonitor reopening stale connection on visibilitychange. visbilityState = #{document.visibilityState}")
|
||||||
@consumer.connection.reopen()
|
@connection.reopen()
|
||||||
, 200
|
, 200
|
||||||
|
|
||||||
now = ->
|
now = ->
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#= require ./connection
|
#= require ./connection
|
||||||
#= require ./connection_monitor
|
|
||||||
#= require ./subscriptions
|
#= require ./subscriptions
|
||||||
#= require ./subscription
|
#= require ./subscription
|
||||||
|
|
||||||
|
@ -19,7 +18,6 @@ class ActionCable.Consumer
|
||||||
constructor: (@url) ->
|
constructor: (@url) ->
|
||||||
@subscriptions = new ActionCable.Subscriptions this
|
@subscriptions = new ActionCable.Subscriptions this
|
||||||
@connection = new ActionCable.Connection this
|
@connection = new ActionCable.Connection this
|
||||||
@connectionMonitor = new ActionCable.ConnectionMonitor this
|
|
||||||
|
|
||||||
send: (data) ->
|
send: (data) ->
|
||||||
@connection.send(data)
|
@connection.send(data)
|
||||||
|
|
Loading…
Reference in a new issue