firehose 1.2.20 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +36 -0
- data/{LICENSE.txt → LICENSE} +6 -6
- data/README.md +389 -139
- data/app/assets/javascripts/firehose.js +258 -0
- data/config/importmap.rb +1 -0
- data/db/migrate/20260214185244_create_firehose_events.rb +23 -0
- data/lib/commands/firehose_command.rb +119 -0
- data/lib/firehose/channel.rb +40 -0
- data/lib/firehose/cleanup_job.rb +21 -0
- data/lib/firehose/engine.rb +36 -0
- data/lib/firehose/helper.rb +40 -0
- data/lib/firehose/models/channel.rb +12 -0
- data/lib/firehose/models/message.rb +11 -0
- data/lib/firehose/queue.rb +44 -0
- data/lib/firehose/server.rb +931 -18
- data/lib/firehose/sse.rb +187 -0
- data/lib/firehose/stream.rb +32 -0
- data/lib/firehose/streamable.rb +25 -0
- data/lib/firehose/websocket.rb +242 -0
- data/lib/firehose.rb +67 -15
- data/lib/generators/firehose/install/install_generator.rb +43 -0
- data/lib/generators/firehose/install/templates/firehose_controller.rb +16 -0
- metadata +40 -428
- data/.env.sample +0 -17
- data/.gitignore +0 -12
- data/.rbenv-version +0 -1
- data/.rspec +0 -1
- data/.travis.yml +0 -16
- data/Gemfile +0 -4
- data/Guardfile +0 -31
- data/Procfile +0 -1
- data/Procfile.dev +0 -4
- data/Rakefile +0 -53
- data/bin/firehose +0 -9
- data/config/evergreen.rb +0 -9
- data/config/rainbows.rb +0 -17
- data/firehose.gemspec +0 -49
- data/lib/assets/javascripts/firehose/base.js.coffee +0 -4
- data/lib/assets/javascripts/firehose/consumer.js.coffee +0 -70
- data/lib/assets/javascripts/firehose/core.js.coffee +0 -5
- data/lib/assets/javascripts/firehose/long_poll.js.coffee +0 -149
- data/lib/assets/javascripts/firehose/transport.js.coffee +0 -42
- data/lib/assets/javascripts/firehose/version.js.coffee.erb +0 -2
- data/lib/assets/javascripts/firehose/web_socket.js.coffee +0 -102
- data/lib/assets/javascripts/firehose.js.coffee +0 -3
- data/lib/assets/javascripts/vendor/json2.js +0 -487
- data/lib/firehose/assets.rb +0 -56
- data/lib/firehose/cli.rb +0 -78
- data/lib/firehose/client/consumer.rb +0 -94
- data/lib/firehose/client/producer.rb +0 -108
- data/lib/firehose/client.rb +0 -10
- data/lib/firehose/logging.rb +0 -32
- data/lib/firehose/rack/app.rb +0 -49
- data/lib/firehose/rack/consumer/http_long_poll.rb +0 -86
- data/lib/firehose/rack/consumer/web_socket.rb +0 -95
- data/lib/firehose/rack/consumer.rb +0 -39
- data/lib/firehose/rack/ping.rb +0 -88
- data/lib/firehose/rack/publisher.rb +0 -53
- data/lib/firehose/rack.rb +0 -32
- data/lib/firehose/rails.rb +0 -7
- data/lib/firehose/server/app.rb +0 -52
- data/lib/firehose/server/channel.rb +0 -80
- data/lib/firehose/server/publisher.rb +0 -134
- data/lib/firehose/server/subscriber.rb +0 -51
- data/lib/firehose/version.rb +0 -4
- data/package.json +0 -5
- data/spec/integrations/integration_test_helper.rb +0 -22
- data/spec/integrations/rainbows_spec.rb +0 -7
- data/spec/integrations/shared_examples.rb +0 -120
- data/spec/integrations/thin_spec.rb +0 -7
- data/spec/javascripts/firehose/base_spec.coffee +0 -2
- data/spec/javascripts/firehose/consumer_spec.coffee +0 -45
- data/spec/javascripts/firehose/long_poll_spec.coffee +0 -44
- data/spec/javascripts/firehose/transport_spec.coffee +0 -32
- data/spec/javascripts/firehose/websocket_spec.coffee +0 -25
- data/spec/javascripts/helpers/spec_helper.js +0 -30
- data/spec/javascripts/support/sinon-1.7.3.js +0 -4290
- data/spec/lib/assets_spec.rb +0 -35
- data/spec/lib/client/consumer_spec.rb +0 -13
- data/spec/lib/client/producer_spec.rb +0 -71
- data/spec/lib/firehose_spec.rb +0 -7
- data/spec/lib/rack/consumer/http_long_poll_spec.rb +0 -12
- data/spec/lib/rack/consumer_spec.rb +0 -19
- data/spec/lib/rack/ping_spec.rb +0 -28
- data/spec/lib/rack/publisher_spec.rb +0 -34
- data/spec/lib/server/app_spec.rb +0 -15
- data/spec/lib/server/channel_spec.rb +0 -164
- data/spec/lib/server/publisher_spec.rb +0 -84
- data/spec/lib/server/subscriber_spec.rb +0 -69
- data/spec/spec_helper.rb +0 -77
data/config/evergreen.rb
DELETED
data/config/rainbows.rb
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Configuration from http://rainbows.rubyforge.org/Rainbows/Configurator.html. Don't juse
|
|
2
|
-
# blindly copy and paste this configuration! Be sure you have read and understand the Rainbows
|
|
3
|
-
# configuration documentation for your environment.
|
|
4
|
-
|
|
5
|
-
Rainbows! do
|
|
6
|
-
use :EventMachine # concurrency model
|
|
7
|
-
worker_connections 400
|
|
8
|
-
keepalive_timeout 0 # disables keepalives
|
|
9
|
-
keepalive_requests 666 # default:100
|
|
10
|
-
client_max_body_size 5 * 1024 * 1024 # 5 megabytes
|
|
11
|
-
client_header_buffer_size 2 * 1024 # 2 kilobytes
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# the rest of the Unicorn configuration...
|
|
15
|
-
worker_processes [ENV['WORKER_PROCESSES'].to_i, 1].max # Default to 1
|
|
16
|
-
working_directory ENV['WORKING_DIRECTORY'] if ENV['WORKING_DIRECTORY']
|
|
17
|
-
logger Firehose.logger
|
data/firehose.gemspec
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
-
require "firehose/version"
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |s|
|
|
6
|
-
s.name = "firehose"
|
|
7
|
-
s.version = Firehose::VERSION
|
|
8
|
-
s.authors = ["Brad Gessler", "Steel Fu", "Paul Cortens", "Zach Zolton"]
|
|
9
|
-
s.email = ["brad@polleverywhere.com", "steel@polleverywhere.com", "paul@polleverywhere.com", "zach@polleverywhere.com"]
|
|
10
|
-
s.homepage = "http://firehose.io/"
|
|
11
|
-
s.summary = %q{Build realtime Ruby web applications}
|
|
12
|
-
s.description = %q{Firehose is a realtime web application toolkit for building realtime Ruby web applications.}
|
|
13
|
-
s.license = "MIT"
|
|
14
|
-
|
|
15
|
-
s.rubyforge_project = "firehose"
|
|
16
|
-
|
|
17
|
-
s.files = `git ls-files`.split("\n")
|
|
18
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
-
s.require_paths = ["lib"]
|
|
21
|
-
|
|
22
|
-
# specify any dependencies here; for example:
|
|
23
|
-
s.add_runtime_dependency "eventmachine", ">= 1.0.0"
|
|
24
|
-
s.add_runtime_dependency "em-hiredis", ">= 0.2.0"
|
|
25
|
-
s.add_runtime_dependency "thor"
|
|
26
|
-
s.add_runtime_dependency "faraday"
|
|
27
|
-
s.add_runtime_dependency "faye-websocket"
|
|
28
|
-
s.add_runtime_dependency "em-http-request", ">= 1.0.0"
|
|
29
|
-
s.add_runtime_dependency "json"
|
|
30
|
-
s.add_runtime_dependency "rack"
|
|
31
|
-
|
|
32
|
-
s.add_development_dependency "rspec", "~> 2"
|
|
33
|
-
s.add_development_dependency "webmock"
|
|
34
|
-
s.add_development_dependency "coffee-script"
|
|
35
|
-
s.add_development_dependency "guard-rspec"
|
|
36
|
-
s.add_development_dependency "guard-bundler"
|
|
37
|
-
s.add_development_dependency "guard-coffeescript"
|
|
38
|
-
s.add_development_dependency "guard-copy"
|
|
39
|
-
s.add_development_dependency "rainbows", "~> 4.4.3"
|
|
40
|
-
s.add_development_dependency "thin"
|
|
41
|
-
s.add_development_dependency "rack-test"
|
|
42
|
-
s.add_development_dependency "async_rack_test"
|
|
43
|
-
s.add_development_dependency "foreman"
|
|
44
|
-
s.add_development_dependency "sprockets"
|
|
45
|
-
s.add_development_dependency "rake"
|
|
46
|
-
s.add_development_dependency "evergreen"
|
|
47
|
-
s.add_development_dependency "capybara-webkit"
|
|
48
|
-
s.add_development_dependency "therubyracer"
|
|
49
|
-
end
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
class Firehose.Consumer
|
|
2
|
-
constructor: (@config = {}) ->
|
|
3
|
-
# Empty handler for messages.
|
|
4
|
-
@config.message ||= ->
|
|
5
|
-
# Empty handler for error handling.
|
|
6
|
-
@config.error ||= ->
|
|
7
|
-
# Empty handler for when we establish a connection.
|
|
8
|
-
@config.connected ||= ->
|
|
9
|
-
# Empty handler for when we're disconnected.
|
|
10
|
-
@config.disconnected ||= ->
|
|
11
|
-
# The initial connection failed. This is probably triggered when a
|
|
12
|
-
# transport, like WebSockets is supported by the browser, but for whatever
|
|
13
|
-
# reason it can't connect (probably a firewall)
|
|
14
|
-
@config.failed ||= ->
|
|
15
|
-
throw "Could not connect"
|
|
16
|
-
# Params that we'll tack on to the URL.
|
|
17
|
-
@config.params ||= {}
|
|
18
|
-
# Do stuff before we send the message into config.message. The sensible
|
|
19
|
-
# default on the webs is to parse JSON.
|
|
20
|
-
@config.parse ||= JSON.parse
|
|
21
|
-
# Make sure we return ourself out of the constructor so we can chain.
|
|
22
|
-
this
|
|
23
|
-
|
|
24
|
-
connect: (delay=0) =>
|
|
25
|
-
promise = @_connectPromise()
|
|
26
|
-
|
|
27
|
-
@config.connectionVerified = @_upgradeTransport
|
|
28
|
-
if Firehose.WebSocket.supported()
|
|
29
|
-
@upgradeTimeout = setTimeout =>
|
|
30
|
-
ws = new Firehose.WebSocket @config
|
|
31
|
-
ws.connect delay
|
|
32
|
-
, 500
|
|
33
|
-
@transport = new Firehose.LongPoll @config
|
|
34
|
-
@transport.connect delay
|
|
35
|
-
|
|
36
|
-
promise
|
|
37
|
-
|
|
38
|
-
stop: =>
|
|
39
|
-
if @upgradeTimeout?
|
|
40
|
-
clearTimeout @upgradeTimeout
|
|
41
|
-
@upgradeTimeout = null
|
|
42
|
-
@transport.stop()
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
_upgradeTransport: (ws) =>
|
|
46
|
-
@transport.stop()
|
|
47
|
-
ws.sendStartingMessageSequence @transport.getLastMessageSequence()
|
|
48
|
-
@transport = ws
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
# Return a promise that will succeed/fail depending on whether or not the
|
|
52
|
-
# initial connection succeeds.
|
|
53
|
-
_connectPromise: =>
|
|
54
|
-
deferred = $.Deferred()
|
|
55
|
-
|
|
56
|
-
origConnected = @config.connected
|
|
57
|
-
@config.connected = =>
|
|
58
|
-
deferred.resolve()
|
|
59
|
-
if origConnected
|
|
60
|
-
@config.connected = origConnected
|
|
61
|
-
origConnected()
|
|
62
|
-
|
|
63
|
-
# origDisconnected = @config.disconnected
|
|
64
|
-
# @config.disconnected = =>
|
|
65
|
-
# deferred.reject()
|
|
66
|
-
# if origDisconnected
|
|
67
|
-
# @config.disconnected = origDisconnected
|
|
68
|
-
# origDisconnected()
|
|
69
|
-
|
|
70
|
-
deferred.promise()
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
class Firehose.LongPoll extends Firehose.Transport
|
|
2
|
-
messageSequenceHeader: 'Pragma'
|
|
3
|
-
name: -> 'LongPoll'
|
|
4
|
-
|
|
5
|
-
# CORS is kinda supported in IE8+ except that its implementation cannot
|
|
6
|
-
# access "simple request" response headers. This means we don't yet have a
|
|
7
|
-
# plan to support IE<10 (when it gets a real XHR2 implementation). Sucks...
|
|
8
|
-
# $.browser.msie and parseInt($.browser.version) >= 8 # DEPRECATED
|
|
9
|
-
@ieSupported: -> (document.documentMode || 10) >= 8
|
|
10
|
-
|
|
11
|
-
@supported: ->
|
|
12
|
-
# IE 8+, FF 3.5+, Chrome 4+, Safari 4+, Opera 12+, iOS 3.2+, Android 2.1+
|
|
13
|
-
if xhr = $.ajaxSettings.xhr()
|
|
14
|
-
"withCredentials" of xhr || Firehose.LongPoll.ieSupported()
|
|
15
|
-
|
|
16
|
-
constructor: (args) ->
|
|
17
|
-
super args
|
|
18
|
-
|
|
19
|
-
@config.ssl ?= false
|
|
20
|
-
|
|
21
|
-
# Configrations specifically for long polling
|
|
22
|
-
@config.longPoll ||= {}
|
|
23
|
-
@config.longPoll.url ||= "#{@_protocol()}:#{@config.uri}"
|
|
24
|
-
# How many ms should we wait before timing out the AJAX connection?
|
|
25
|
-
@config.longPoll.timeout ||= 25000
|
|
26
|
-
# TODO - What is @_lagTime for? Can't we just use the @_timeout value?
|
|
27
|
-
# We use the lag time to make the client live longer than the server.
|
|
28
|
-
@_lagTime = 5000
|
|
29
|
-
@_timeout = @config.longPoll.timeout + @_lagTime
|
|
30
|
-
@_okInterval = @config.okInterval || 0
|
|
31
|
-
@_stopRequestLoop = false
|
|
32
|
-
|
|
33
|
-
# Protocol schema we should use for talking to firehose server.
|
|
34
|
-
_protocol: =>
|
|
35
|
-
if @config.ssl then "https" else "http"
|
|
36
|
-
|
|
37
|
-
_request: =>
|
|
38
|
-
return if @_stopRequestLoop
|
|
39
|
-
# Set the Last Message Sequence in a query string.
|
|
40
|
-
# Ideally we'd use an HTTP header, but android devices don't let us
|
|
41
|
-
# set any HTTP headers for CORS requests.
|
|
42
|
-
data = @config.params
|
|
43
|
-
data.last_message_sequence = @_lastMessageSequence
|
|
44
|
-
# TODO: Some of these options will be deprecated in jQuery 1.8
|
|
45
|
-
# See: http://api.jquery.com/jQuery.ajax/#jqXHR
|
|
46
|
-
@_lastRequest = $.ajax
|
|
47
|
-
url: @config.longPoll.url
|
|
48
|
-
firehose: true
|
|
49
|
-
crossDomain: true
|
|
50
|
-
data: data
|
|
51
|
-
timeout: @_timeout
|
|
52
|
-
success: @_success
|
|
53
|
-
error: @_error
|
|
54
|
-
cache: false
|
|
55
|
-
|
|
56
|
-
stop: =>
|
|
57
|
-
@_stopRequestLoop = true
|
|
58
|
-
if @_lastRequest?
|
|
59
|
-
try @_lastRequest.abort() catch e
|
|
60
|
-
delete @_lastRequest
|
|
61
|
-
if @_lastPingRequest?
|
|
62
|
-
try @_lastPingRequest.abort() catch e
|
|
63
|
-
delete @_lastPingRequest
|
|
64
|
-
|
|
65
|
-
_success: (data, status, jqXhr) =>
|
|
66
|
-
if @_needToNotifyOfReconnect or not @_succeeded
|
|
67
|
-
@_needToNotifyOfReconnect = false
|
|
68
|
-
@_open data
|
|
69
|
-
return if @_stopRequestLoop
|
|
70
|
-
if jqXhr.status is 200
|
|
71
|
-
# Of course, IE's XDomainRequest doesn't support non-200 success codes.
|
|
72
|
-
try
|
|
73
|
-
{message, last_sequence} = JSON.parse jqXhr.responseText
|
|
74
|
-
@_lastMessageSequence = last_sequence
|
|
75
|
-
@config.message @config.parse message
|
|
76
|
-
catch e
|
|
77
|
-
@connect @_okInterval
|
|
78
|
-
|
|
79
|
-
_ping: =>
|
|
80
|
-
# Ping long poll server to verify internet connectivity
|
|
81
|
-
# jQuery CORS doesn't support timeouts and there is no way to access xhr2 object
|
|
82
|
-
# directly so we can't manually set a timeout.
|
|
83
|
-
@_lastPingRequest = $.ajax
|
|
84
|
-
url: @config.longPoll.url
|
|
85
|
-
method: 'HEAD'
|
|
86
|
-
crossDomain: true
|
|
87
|
-
firehose: true
|
|
88
|
-
data: @config.params
|
|
89
|
-
success: =>
|
|
90
|
-
if @_needToNotifyOfReconnect
|
|
91
|
-
@_needToNotifyOfReconnect = false
|
|
92
|
-
@config.connected @
|
|
93
|
-
|
|
94
|
-
# We need this custom handler to have the connection status
|
|
95
|
-
# properly displayed
|
|
96
|
-
_error: (jqXhr, status, error) =>
|
|
97
|
-
unless @_needToNotifyOfReconnect or @_stopRequestLoop
|
|
98
|
-
@_needToNotifyOfReconnect = true
|
|
99
|
-
@config.disconnected()
|
|
100
|
-
unless @_stopRequestLoop
|
|
101
|
-
# Ping the server to make sure this isn't a network connectivity error
|
|
102
|
-
setTimeout @_ping, @_retryDelay + @_lagTime
|
|
103
|
-
# Reconnect with delay
|
|
104
|
-
setTimeout @_request, @_retryDelay
|
|
105
|
-
|
|
106
|
-
# Let's try to hack in support for IE8-9 via the XDomainRequest object!
|
|
107
|
-
# This was adapted from code shamelessly stolen from:
|
|
108
|
-
# https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js
|
|
109
|
-
if $?.browser?.msie and parseInt($.browser.version, 10) in [8, 9]
|
|
110
|
-
jQuery.ajaxTransport (s) ->
|
|
111
|
-
if s.crossDomain and s.async and s.firehose
|
|
112
|
-
if s.timeout
|
|
113
|
-
s.xdrTimeout = s.timeout
|
|
114
|
-
delete s.timeout
|
|
115
|
-
xdr = undefined
|
|
116
|
-
return {
|
|
117
|
-
send: (_, complete) ->
|
|
118
|
-
callback = (status, statusText, responses, responseHeaders) ->
|
|
119
|
-
xdr.onload = xdr.onerror = xdr.ontimeout = jQuery.noop
|
|
120
|
-
xdr = undefined
|
|
121
|
-
complete status, statusText, responses, responseHeaders
|
|
122
|
-
|
|
123
|
-
xdr = new XDomainRequest()
|
|
124
|
-
|
|
125
|
-
xdr.open s.type, s.url
|
|
126
|
-
|
|
127
|
-
xdr.onload = ->
|
|
128
|
-
headers = "Content-Type: #{xdr.contentType}"
|
|
129
|
-
callback 200, "OK", {text: xdr.responseText}, headers
|
|
130
|
-
|
|
131
|
-
xdr.onerror = -> callback 404, "Not Found"
|
|
132
|
-
|
|
133
|
-
# This is critical for long poll to work in IE9.
|
|
134
|
-
# Without it, the initial request will work but
|
|
135
|
-
# subsequent requests will fail silently.
|
|
136
|
-
# http://social.msdn.microsoft.com/Forums/ie/en-US/30ef3add-767c-4436-b8a9-f1ca19b4812e/ie9-rtm-xdomainrequest-issued-requests-may-abort-if-all-event-handlers-not-specified?forum=iewebdevelopment
|
|
137
|
-
xdr.onprogress = -> {}
|
|
138
|
-
|
|
139
|
-
if s.xdrTimeout?
|
|
140
|
-
xdr.ontimeout = -> callback 0, "timeout"
|
|
141
|
-
xdr.timeout = s.xdrTimeout
|
|
142
|
-
|
|
143
|
-
xdr.send (s.hasContent and s.data) or null
|
|
144
|
-
|
|
145
|
-
abort: ->
|
|
146
|
-
if xdr?
|
|
147
|
-
xdr.onerror = jQuery.noop()
|
|
148
|
-
xdr.abort()
|
|
149
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
class Firehose.Transport
|
|
2
|
-
# Class method to determine whether transport is supported by the current browser. Note that while
|
|
3
|
-
# the transport may be supported by the browser, its possible that the network connection won't
|
|
4
|
-
# succeed. That should be accounted for during the initial connecting to the server.
|
|
5
|
-
@supported: =>
|
|
6
|
-
false
|
|
7
|
-
|
|
8
|
-
constructor: (config={}) ->
|
|
9
|
-
@config = config
|
|
10
|
-
@_retryDelay = 3000
|
|
11
|
-
@
|
|
12
|
-
|
|
13
|
-
# Lets rock'n'roll! Connect to the server.
|
|
14
|
-
connect: (delay = 0) =>
|
|
15
|
-
setTimeout @_request, delay
|
|
16
|
-
this
|
|
17
|
-
|
|
18
|
-
# Hey subclasses:
|
|
19
|
-
name: -> throw 'not implemented in base Transport' # implement this to identify transport type
|
|
20
|
-
stop: -> throw 'not implemented in base Transport' # implement this to stop receiving messages
|
|
21
|
-
_request: -> throw 'not implemented in base Transport' # implement this to handle requests
|
|
22
|
-
|
|
23
|
-
# Default error handler
|
|
24
|
-
_error: (event) =>
|
|
25
|
-
if @_succeeded
|
|
26
|
-
# Lets try to connect again with delay
|
|
27
|
-
@config.disconnected()
|
|
28
|
-
@connect(@_retryDelay)
|
|
29
|
-
else @config.failed @
|
|
30
|
-
|
|
31
|
-
# Default connection established handler
|
|
32
|
-
_open: (event) =>
|
|
33
|
-
@_succeeded = true
|
|
34
|
-
@config.connected(@)
|
|
35
|
-
|
|
36
|
-
# Default connection closed handler
|
|
37
|
-
_close: (event) =>
|
|
38
|
-
@config.disconnected()
|
|
39
|
-
|
|
40
|
-
# Useful for reconnecting after any networking hiccups
|
|
41
|
-
getLastMessageSequence: =>
|
|
42
|
-
@_lastMessageSequence or 0
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
INITIAL_PING_TIMEOUT = 2000
|
|
2
|
-
KEEPALIVE_PING_TIMEOUT = 20000
|
|
3
|
-
|
|
4
|
-
class Firehose.WebSocket extends Firehose.Transport
|
|
5
|
-
name: -> 'WebSocket'
|
|
6
|
-
|
|
7
|
-
@ieSupported:-> (document.documentMode || 10) > 9
|
|
8
|
-
@supported :-> (if module?.exports? then global else window).WebSocket? # Check if WebSocket is an object in the window.
|
|
9
|
-
|
|
10
|
-
constructor: (args) ->
|
|
11
|
-
super args
|
|
12
|
-
# Configrations specifically for web sockets
|
|
13
|
-
@config.webSocket ||= {}
|
|
14
|
-
@config.webSocket.connectionVerified = @config.connectionVerified
|
|
15
|
-
|
|
16
|
-
_request: =>
|
|
17
|
-
# Run this is a try/catch block because IE10 inside of a .NET control
|
|
18
|
-
# complains about security zones.
|
|
19
|
-
try
|
|
20
|
-
@socket = new (if module?.exports? then global else window).WebSocket "#{@_protocol()}:#{@config.uri}?#{$.param @config.params}"
|
|
21
|
-
@socket.onopen = @_open
|
|
22
|
-
@socket.onclose = @_close
|
|
23
|
-
@socket.onerror = @_error
|
|
24
|
-
@socket.onmessage = @_lookForInitialPong
|
|
25
|
-
catch err
|
|
26
|
-
console?.log(err)
|
|
27
|
-
|
|
28
|
-
# Protocol schema we should use for talking to firehose server.
|
|
29
|
-
_protocol: =>
|
|
30
|
-
if @config.ssl then "wss" else "ws"
|
|
31
|
-
|
|
32
|
-
_open: =>
|
|
33
|
-
sendPing @socket
|
|
34
|
-
|
|
35
|
-
_lookForInitialPong: (event) =>
|
|
36
|
-
@_restartKeepAlive()
|
|
37
|
-
if isPong(try JSON.parse event.data catch e then {})
|
|
38
|
-
if @_lastMessageSequence?
|
|
39
|
-
# don't callback to connectionVerified on subsequent reconnects
|
|
40
|
-
@sendStartingMessageSequence @_lastMessageSequence
|
|
41
|
-
else @config.webSocket.connectionVerified @
|
|
42
|
-
|
|
43
|
-
sendStartingMessageSequence: (message_sequence) =>
|
|
44
|
-
@_lastMessageSequence = message_sequence
|
|
45
|
-
@socket.onmessage = @_message
|
|
46
|
-
@socket.send JSON.stringify {message_sequence}
|
|
47
|
-
@_needToNotifyOfDisconnect = true
|
|
48
|
-
Firehose.Transport::_open.call @
|
|
49
|
-
|
|
50
|
-
stop: =>
|
|
51
|
-
@_cleanUp()
|
|
52
|
-
|
|
53
|
-
_message: (event) =>
|
|
54
|
-
frame = @config.parse event.data
|
|
55
|
-
@_restartKeepAlive()
|
|
56
|
-
unless isPong frame
|
|
57
|
-
try
|
|
58
|
-
@_lastMessageSequence = frame.last_sequence
|
|
59
|
-
@config.message @config.parse frame.message
|
|
60
|
-
catch e
|
|
61
|
-
|
|
62
|
-
_close: (event) =>
|
|
63
|
-
if event?.wasClean then @_cleanUp()
|
|
64
|
-
else @_error event
|
|
65
|
-
|
|
66
|
-
_error: (event) =>
|
|
67
|
-
@_cleanUp()
|
|
68
|
-
if @_needToNotifyOfDisconnect
|
|
69
|
-
@_needToNotifyOfDisconnect = false
|
|
70
|
-
@config.disconnected()
|
|
71
|
-
if @_succeeded then @connect @_retryDelay
|
|
72
|
-
else @config.failed @
|
|
73
|
-
|
|
74
|
-
_cleanUp: =>
|
|
75
|
-
@_clearKeepalive()
|
|
76
|
-
if @socket?
|
|
77
|
-
@socket.onopen = null
|
|
78
|
-
@socket.onclose = null
|
|
79
|
-
@socket.onerror = null
|
|
80
|
-
@socket.onmessage = null
|
|
81
|
-
@socket.close()
|
|
82
|
-
delete @socket
|
|
83
|
-
|
|
84
|
-
_restartKeepAlive: =>
|
|
85
|
-
doPing = =>
|
|
86
|
-
sendPing @socket
|
|
87
|
-
setNextKeepAlive()
|
|
88
|
-
setNextKeepAlive = =>
|
|
89
|
-
@keepaliveTimeout = setTimeout doPing, KEEPALIVE_PING_TIMEOUT
|
|
90
|
-
@_clearKeepalive()
|
|
91
|
-
setNextKeepAlive()
|
|
92
|
-
|
|
93
|
-
_clearKeepalive: =>
|
|
94
|
-
if @keepaliveTimeout?
|
|
95
|
-
clearTimeout @keepaliveTimeout
|
|
96
|
-
@keepaliveTimeout = null
|
|
97
|
-
|
|
98
|
-
sendPing = (socket) ->
|
|
99
|
-
socket.send JSON.stringify ping: 'PING'
|
|
100
|
-
|
|
101
|
-
isPong = (o) ->
|
|
102
|
-
o.pong is 'PONG'
|