aboutsummaryrefslogtreecommitdiffstats
path: root/actioncable/app/assets/javascripts/action_cable/connection.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'actioncable/app/assets/javascripts/action_cable/connection.coffee')
-rw-r--r--actioncable/app/assets/javascripts/action_cable/connection.coffee48
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..3a139acf3a 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("Attempted 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()