diff options
Diffstat (limited to 'actioncable/app/assets/javascripts/action_cable/connection.coffee')
-rw-r--r-- | actioncable/app/assets/javascripts/action_cable/connection.coffee | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/actioncable/app/assets/javascripts/action_cable/connection.coffee b/actioncable/app/assets/javascripts/action_cable/connection.coffee index fbd7dbd35b..92272cc5b8 100644 --- a/actioncable/app/assets/javascripts/action_cable/connection.coffee +++ b/actioncable/app/assets/javascripts/action_cable/connection.coffee @@ -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. {message_types} = ActionCable.INTERNAL @@ -6,7 +8,8 @@ class ActionCable.Connection @reopenDelay: 500 constructor: (@consumer) -> - @open() + {@subscriptions} = @consumer + @monitor = new ActionCable.ConnectionMonitor this send: (data) -> if @isOpen() @@ -16,28 +19,39 @@ class ActionCable.Connection false open: => - if @webSocket and not @isState("closed") + if @isActive() + ActionCable.log("Attemped to open WebSocket, but existing socket is #{@getState()}") throw new Error("Existing connection must be closed before opening") else + ActionCable.log("Opening WebSocket, current state is #{@getState()}") + @uninstallEventHandlers() if @webSocket? @webSocket = new WebSocket(@consumer.url) @installEventHandlers() + @monitor.start() true close: -> @webSocket?.close() reopen: -> - if @isState("closed") - @open() - else + ActionCable.log("Reopening WebSocket, current state is #{@getState()}") + if @isActive() try @close() + catch error + ActionCable.log("Failed to reopen WebSocket", error) finally + ActionCable.log("Reopening WebSocket in #{@constructor.reopenDelay}ms") setTimeout(@open, @constructor.reopenDelay) + else + @open() isOpen: -> @isState("open") + isActive: -> + @isState("open", "connecting") + # Private isState: (states...) -> @@ -53,29 +67,41 @@ class ActionCable.Connection @webSocket["on#{eventName}"] = handler return + uninstallEventHandlers: -> + for eventName of @events + @webSocket["on#{eventName}"] = -> + return + events: message: (event) -> {identifier, message, type} = JSON.parse(event.data) - switch type + when message_types.welcome + @monitor.recordConnect() + when message_types.ping + @monitor.recordPing() when message_types.confirmation - @consumer.subscriptions.notify(identifier, "connected") + @subscriptions.notify(identifier, "connected") when message_types.rejection - @consumer.subscriptions.reject(identifier) + @subscriptions.reject(identifier) else - @consumer.subscriptions.notify(identifier, "received", message) + @subscriptions.notify(identifier, "received", message) open: -> + ActionCable.log("WebSocket onopen event") @disconnected = false - @consumer.subscriptions.reload() + @subscriptions.reload() close: -> + ActionCable.log("WebSocket onclose event") @disconnect() error: -> + ActionCable.log("WebSocket onerror event") @disconnect() disconnect: -> return if @disconnected @disconnected = true - @consumer.subscriptions.notifyAll("disconnected") + @subscriptions.notifyAll("disconnected") + @monitor.recordDisconnect() |