firehose 1.3.6 → 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.
Files changed (104) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +31 -10
  3. data/{LICENSE.txt → LICENSE} +6 -6
  4. data/README.md +379 -187
  5. data/app/assets/javascripts/firehose.js +258 -0
  6. data/config/importmap.rb +1 -0
  7. data/db/migrate/20260214185244_create_firehose_events.rb +23 -0
  8. data/lib/commands/firehose_command.rb +119 -0
  9. data/lib/firehose/channel.rb +40 -0
  10. data/lib/firehose/cleanup_job.rb +21 -0
  11. data/lib/firehose/engine.rb +36 -0
  12. data/lib/firehose/helper.rb +40 -0
  13. data/lib/firehose/models/channel.rb +12 -0
  14. data/lib/firehose/models/message.rb +11 -0
  15. data/lib/firehose/queue.rb +44 -0
  16. data/lib/firehose/server.rb +930 -17
  17. data/lib/firehose/sse.rb +187 -0
  18. data/lib/firehose/stream.rb +32 -0
  19. data/lib/firehose/streamable.rb +25 -0
  20. data/lib/firehose/websocket.rb +242 -0
  21. data/lib/firehose.rb +67 -15
  22. data/lib/generators/firehose/install/install_generator.rb +43 -0
  23. data/lib/generators/firehose/install/templates/firehose_controller.rb +16 -0
  24. metadata +39 -366
  25. data/.codeclimate.yml +0 -29
  26. data/.dockerignore +0 -2
  27. data/.env.sample +0 -17
  28. data/.gitignore +0 -14
  29. data/.rspec +0 -1
  30. data/.rubocop.yml +0 -1156
  31. data/.ruby-version +0 -1
  32. data/.travis.yml +0 -12
  33. data/Dockerfile +0 -11
  34. data/Gemfile +0 -6
  35. data/Procfile +0 -1
  36. data/Procfile.dev +0 -3
  37. data/Rakefile +0 -64
  38. data/bin/firehose +0 -9
  39. data/coffeelint.json +0 -129
  40. data/config/rainbows.rb +0 -17
  41. data/docker-compose.yml +0 -17
  42. data/firehose.gemspec +0 -45
  43. data/karma.config.coffee +0 -89
  44. data/lib/assets/javascripts/firehose/base.js.coffee +0 -4
  45. data/lib/assets/javascripts/firehose/consumer.js.coffee +0 -86
  46. data/lib/assets/javascripts/firehose/core.js.coffee +0 -6
  47. data/lib/assets/javascripts/firehose/long_poll.js.coffee +0 -210
  48. data/lib/assets/javascripts/firehose/multiplexed_consumer.js.coffee +0 -74
  49. data/lib/assets/javascripts/firehose/transport.js.coffee +0 -44
  50. data/lib/assets/javascripts/firehose/version.js.coffee.erb +0 -2
  51. data/lib/assets/javascripts/firehose/web_socket.js.coffee +0 -148
  52. data/lib/assets/javascripts/firehose.js.coffee +0 -2
  53. data/lib/firehose/assets.rb +0 -56
  54. data/lib/firehose/cli.rb +0 -79
  55. data/lib/firehose/client/consumer.rb +0 -94
  56. data/lib/firehose/client/producer.rb +0 -114
  57. data/lib/firehose/client.rb +0 -10
  58. data/lib/firehose/logging.rb +0 -32
  59. data/lib/firehose/rack/app.rb +0 -49
  60. data/lib/firehose/rack/consumer/http_long_poll.rb +0 -159
  61. data/lib/firehose/rack/consumer/web_socket.rb +0 -200
  62. data/lib/firehose/rack/consumer.rb +0 -78
  63. data/lib/firehose/rack/ping.rb +0 -88
  64. data/lib/firehose/rack/publisher.rb +0 -59
  65. data/lib/firehose/rack.rb +0 -32
  66. data/lib/firehose/rails.rb +0 -7
  67. data/lib/firehose/server/app.rb +0 -52
  68. data/lib/firehose/server/channel.rb +0 -72
  69. data/lib/firehose/server/message_buffer.rb +0 -59
  70. data/lib/firehose/server/publisher.rb +0 -133
  71. data/lib/firehose/server/redis.rb +0 -32
  72. data/lib/firehose/server/subscriber.rb +0 -51
  73. data/lib/firehose/version.rb +0 -4
  74. data/package.json +0 -17
  75. data/spec/integrations/integration_test_helper.rb +0 -22
  76. data/spec/integrations/rainbows_spec.rb +0 -7
  77. data/spec/integrations/shared_examples.rb +0 -202
  78. data/spec/integrations/thin_spec.rb +0 -7
  79. data/spec/javascripts/firehose/base_spec.coffee +0 -2
  80. data/spec/javascripts/firehose/consumer_spec.coffee +0 -45
  81. data/spec/javascripts/firehose/long_poll_spec.coffee +0 -44
  82. data/spec/javascripts/firehose/multiplexed_consumer_spec.coffee +0 -72
  83. data/spec/javascripts/firehose/transport_spec.coffee +0 -30
  84. data/spec/javascripts/firehose/websocket_spec.coffee +0 -27
  85. data/spec/javascripts/helpers/spec_helper.js +0 -31
  86. data/spec/javascripts/support/jquery-1.11.1.js +0 -10308
  87. data/spec/javascripts/support/json2.js +0 -487
  88. data/spec/javascripts/support/sinon-1.7.3.js +0 -4290
  89. data/spec/javascripts/support/spec_helper.coffee +0 -3
  90. data/spec/lib/assets_spec.rb +0 -35
  91. data/spec/lib/client/consumer_spec.rb +0 -13
  92. data/spec/lib/client/producer_spec.rb +0 -71
  93. data/spec/lib/firehose_spec.rb +0 -7
  94. data/spec/lib/rack/consumer/http_long_poll_spec.rb +0 -30
  95. data/spec/lib/rack/consumer_spec.rb +0 -19
  96. data/spec/lib/rack/ping_spec.rb +0 -28
  97. data/spec/lib/rack/publisher_spec.rb +0 -34
  98. data/spec/lib/server/app_spec.rb +0 -15
  99. data/spec/lib/server/channel_spec.rb +0 -178
  100. data/spec/lib/server/message_buffer_spec.rb +0 -148
  101. data/spec/lib/server/publisher_spec.rb +0 -91
  102. data/spec/lib/server/redis_spec.rb +0 -13
  103. data/spec/lib/server/subscriber_spec.rb +0 -70
  104. data/spec/spec_helper.rb +0 -84
@@ -1,210 +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
- @_lastMessageSequence = 0
33
-
34
- # Protocol schema we should use for talking to firehose server.
35
- _protocol: =>
36
- if @config.ssl then "https" else "http"
37
-
38
- _request: =>
39
- return if @_stopRequestLoop
40
- # Set the Last Message Sequence in a query string.
41
- # Ideally we'd use an HTTP header, but android devices don't let us
42
- # set any HTTP headers for CORS requests.
43
- data = @_requestParams()
44
- data.last_message_sequence = @_lastMessageSequence
45
- # TODO: Some of these options will be deprecated in jQuery 1.8
46
- # See: http://api.jquery.com/jQuery.ajax/#jqXHR
47
- @_lastRequest = $.ajax
48
- url: @config.longPoll.url
49
- firehose: true
50
- crossDomain: true
51
- data: data
52
- timeout: @_timeout
53
- success: @_success
54
- error: @_error
55
- cache: false
56
-
57
- _requestParams: =>
58
- @config.params
59
-
60
- stop: =>
61
- @_stopRequestLoop = true
62
- if @_lastRequest?
63
- try @_lastRequest.abort() catch e
64
- delete @_lastRequest
65
- if @_lastPingRequest?
66
- try @_lastPingRequest.abort() catch e
67
- delete @_lastPingRequest
68
-
69
- _success: (data, status, jqXhr) =>
70
- if @_needToNotifyOfReconnect or not @_succeeded
71
- @_needToNotifyOfReconnect = false
72
- @_open data
73
- return if @_stopRequestLoop
74
- if jqXhr.status is 200
75
- # Of course, IE's XDomainRequest doesn't support non-200 success codes.
76
- try
77
- {message, last_sequence} = JSON.parse jqXhr.responseText
78
- @_lastMessageSequence = last_sequence || 0
79
- @config.message @config.parse message
80
- catch e
81
- @connect @_okInterval
82
-
83
- _ping: =>
84
- # Ping long poll server to verify internet connectivity
85
- # jQuery CORS doesn't support timeouts and there is no way to access xhr2 object
86
- # directly so we can't manually set a timeout.
87
- @_lastPingRequest = $.ajax
88
- url: @config.uri
89
- method: 'HEAD'
90
- crossDomain: true
91
- firehose: true
92
- data: @_requestParams()
93
- success: =>
94
- if @_needToNotifyOfReconnect
95
- @_needToNotifyOfReconnect = false
96
- @config.connected @
97
-
98
- # We need this custom handler to have the connection status
99
- # properly displayed
100
- _error: (jqXhr, status, error) =>
101
- unless @_needToNotifyOfReconnect or @_stopRequestLoop
102
- @_needToNotifyOfReconnect = true
103
- @config.disconnected()
104
- unless @_stopRequestLoop
105
- # Ping the server to make sure this isn't a network connectivity error
106
- setTimeout @_ping, @_retryDelay + @_lagTime
107
- # Reconnect with delay
108
- setTimeout @_request, @_retryDelay
109
-
110
- # Let's try to hack in support for IE8-9 via the XDomainRequest object!
111
- # This was adapted from code shamelessly stolen from:
112
- # https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js
113
- if $?.browser?.msie and parseInt($.browser.version, 10) in [8, 9]
114
- jQuery.ajaxTransport (s) ->
115
- if s.crossDomain and s.async and s.firehose
116
- if s.timeout
117
- s.xdrTimeout = s.timeout
118
- delete s.timeout
119
- xdr = undefined
120
- return {
121
- send: (_, complete) ->
122
- callback = (status, statusText, responses, responseHeaders) ->
123
- xdr.onload = xdr.onerror = xdr.ontimeout = jQuery.noop
124
- xdr = undefined
125
- complete status, statusText, responses, responseHeaders
126
-
127
- xdr = new XDomainRequest()
128
-
129
- xdr.open s.type, s.url
130
-
131
- xdr.onload = ->
132
- headers = "Content-Type: #{xdr.contentType}"
133
- callback 200, "OK", {text: xdr.responseText}, headers
134
-
135
- xdr.onerror = -> callback 404, "Not Found"
136
-
137
- # This is critical for long poll to work in IE9.
138
- # Without it, the initial request will work but
139
- # subsequent requests will fail silently.
140
- # 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
141
- xdr.onprogress = -> {}
142
-
143
- if s.xdrTimeout?
144
- xdr.ontimeout = -> callback 0, "timeout"
145
- xdr.timeout = s.xdrTimeout
146
-
147
- xdr.send (s.hasContent and s.data) or null
148
-
149
- abort: ->
150
- if xdr?
151
- xdr.onerror = jQuery.noop()
152
- xdr.abort()
153
- }
154
-
155
- class Firehose.MultiplexedLongPoll extends Firehose.LongPoll
156
- constructor: (args) ->
157
- super args
158
- @_lastMessageSequence = {}
159
-
160
- subscribe: (channel, opts) =>
161
- # nothing to be done
162
-
163
- unsubscribe: (channelNames...) =>
164
- # same here
165
-
166
- _request: =>
167
- return if @_stopRequestLoop
168
- data = @_subscriptions()
169
-
170
- @_lastRequest = $.ajax
171
- url: @config.uri
172
- firehose: true
173
- crossDomain: true
174
- method: "POST"
175
- data: data
176
- dataType: "json"
177
- timeout: @_timeout
178
- success: @_success
179
- error: @_error
180
- cache: false
181
-
182
- _updateLastMessageSequences: =>
183
- for channel, opts of @config.channels
184
- if seq = @_lastMessageSequence[channel]
185
- opts.last_sequence = seq
186
- else
187
- unless opts.last_sequence
188
- opts.last_sequence = 0
189
-
190
- _subscriptions: =>
191
- @_updateLastMessageSequences()
192
- subs = {}
193
- for channel, opts of @config.channels
194
- subs[channel] = opts.last_sequence || 0
195
- JSON.stringify(subs)
196
-
197
- _success: (data, status, jqXhr) =>
198
- if @_needToNotifyOfReconnect or not @_succeeded
199
- @_needToNotifyOfReconnect = false
200
- @_open data
201
- return if @_stopRequestLoop
202
- if jqXhr.status is 200
203
- # Of course, IE's XDomainRequest doesn't support non-200 success codes.
204
- try
205
- message = JSON.parse jqXhr.responseText
206
- @_lastMessageSequence ||= {}
207
- @_lastMessageSequence[message.channel] = message.last_sequence
208
- @config.message message
209
- catch e
210
- @connect @_okInterval
@@ -1,74 +0,0 @@
1
- Firehose.multiplexChannel = "channels@firehose"
2
-
3
- class Firehose.MultiplexedConsumer extends Firehose.Consumer
4
- @subscriptionQuery: (config) ->
5
- {
6
- subscribe: [
7
- "#{channel}!#{opts.last_sequence || 0}" for channel, opts of config.channels
8
- ].join(",")
9
- }
10
-
11
- @normalizeChannels: (config) ->
12
- for chan, opts of config.channels
13
- if chan[0] != "/"
14
- delete config.channels[chan]
15
- config.channels["/" + chan] = opts
16
-
17
- @normalizeChannel: (channel) ->
18
- if channel[0] != "/"
19
- return "/" + channel
20
- else
21
- return channel
22
-
23
- constructor: (@config = {}) ->
24
- @messageHandlers = {}
25
- @config.message ||= @message
26
- @config.channels ||= {}
27
- @config.uri += Firehose.multiplexChannel
28
-
29
- @_updateSubscriptions()
30
-
31
- for channel, opts of @config.channels
32
- @_addSubscriptionHandler(channel, opts)
33
-
34
- super(@config)
35
-
36
- websocketTransport: (config) =>
37
- new Firehose.MultiplexedWebSocket(config)
38
-
39
- longpollTransport: (config) =>
40
- new Firehose.MultiplexedLongPoll(config)
41
-
42
- message: (msg) =>
43
- if handler = @messageHandlers[msg.channel]
44
- handler(@config.parse msg.message)
45
-
46
- _addSubscriptionHandler: (channel, opts) =>
47
- if opts.message
48
- @messageHandlers[channel] = opts.message
49
-
50
- _removeSubscriptionHandler: (channelNames...) =>
51
- for chan in channelNames
52
- delete @messageHandlers[chan]
53
-
54
- _updateSubscriptions: =>
55
- Firehose.MultiplexedConsumer.normalizeChannels(@config)
56
-
57
- subscribe: (channel, opts = {}) =>
58
- channel = Firehose.MultiplexedConsumer.normalizeChannel(channel)
59
- @config.channels[channel] = opts
60
-
61
- @_updateSubscriptions()
62
- @_addSubscriptionHandler(channel, opts)
63
- @transport.subscribe(channel, opts)
64
-
65
- unsubscribe: (channelNames...) =>
66
- return unless @connected()
67
-
68
- for channel in channelNames
69
- channel = Firehose.MultiplexedConsumer.normalizeChannel(channel)
70
- delete @config.channels[channel]
71
-
72
- @_updateSubscriptions()
73
- @_removeSubscriptionHandler(channelNames...)
74
- @transport.unsubscribe(channelNames...)
@@ -1,44 +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
- @config.params ||= {}
11
-
12
- @_retryDelay = 3000
13
- @
14
-
15
- # Lets rock'n'roll! Connect to the server.
16
- connect: (delay = 0) =>
17
- setTimeout @_request, delay
18
- this
19
-
20
- # Hey subclasses:
21
- name: -> throw 'not implemented in base Transport' # implement this to identify transport type
22
- stop: -> throw 'not implemented in base Transport' # implement this to stop receiving messages
23
- _request: -> throw 'not implemented in base Transport' # implement this to handle requests
24
-
25
- # Default error handler
26
- _error: (event) =>
27
- if @_succeeded
28
- # Lets try to connect again with delay
29
- @config.disconnected()
30
- @connect(@_retryDelay)
31
- else @config.failed @
32
-
33
- # Default connection established handler
34
- _open: (event) =>
35
- @_succeeded = true
36
- @config.connected(@)
37
-
38
- # Default connection closed handler
39
- _close: (event) =>
40
- @config.disconnected()
41
-
42
- # Useful for reconnecting after any networking hiccups
43
- getLastMessageSequence: =>
44
- @_lastMessageSequence or 0
@@ -1,2 +0,0 @@
1
- Firehose.version = "<%= Firehose::VERSION %>"
2
- Firehose.codeName = "<%= Firehose::CODENAME %>"
@@ -1,148 +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
- _sendMessage: (message) =>
17
- @socket?.send(JSON.stringify message)
18
-
19
- _request: =>
20
- # Run this in a try/catch block because IE10 inside of a .NET control
21
- # complains about security zones.
22
- try
23
- @socket = new (if module?.exports? then global else window).WebSocket "#{@_protocol()}:#{@config.uri}?#{$.param @_requestParams()}"
24
- @socket.onopen = @_open
25
- @socket.onclose = @_close
26
- @socket.onerror = @_error
27
- @socket.onmessage = @_lookForInitialPong
28
- catch err
29
- console?.log(err)
30
-
31
- # Protocol schema we should use for talking to firehose server.
32
- _protocol: =>
33
- if @config.ssl then "wss" else "ws"
34
-
35
- _requestParams: =>
36
- @config.params
37
-
38
- _open: =>
39
- sendPing @socket
40
-
41
- _lookForInitialPong: (event) =>
42
- @_restartKeepAlive()
43
- if isPong(try JSON.parse event.data catch e then {})
44
- if @_lastMessageSequence?
45
- # don't callback to connectionVerified on subsequent reconnects
46
- @sendStartingMessageSequence @_lastMessageSequence
47
- else @config.webSocket.connectionVerified @
48
-
49
- sendStartingMessageSequence: (message_sequence) =>
50
- @_lastMessageSequence = message_sequence
51
- @socket.onmessage = @_message
52
- @_sendMessage({message_sequence})
53
- @_needToNotifyOfDisconnect = true
54
- Firehose.Transport::_open.call @
55
-
56
- stop: =>
57
- @_cleanUp()
58
-
59
- _message: (event) =>
60
- frame = @config.parse event.data
61
- @_restartKeepAlive()
62
- unless isPong frame
63
- try
64
- @_lastMessageSequence = frame.last_sequence
65
- @config.message @config.parse frame.message
66
- catch e
67
-
68
- _close: (event) =>
69
- if event?.wasClean then @_cleanUp()
70
- else @_error event
71
-
72
- _error: (event) =>
73
- @_cleanUp()
74
- if @_needToNotifyOfDisconnect
75
- @_needToNotifyOfDisconnect = false
76
- @config.disconnected()
77
- if @_succeeded
78
- @connect @_retryDelay
79
- else if @config.failed
80
- @config.failed @
81
-
82
- _cleanUp: =>
83
- @_clearKeepalive()
84
- if @socket?
85
- @socket.onopen = null
86
- @socket.onclose = null
87
- @socket.onerror = null
88
- @socket.onmessage = null
89
- @socket.close()
90
- delete @socket
91
-
92
- _restartKeepAlive: =>
93
- doPing = =>
94
- sendPing @socket
95
- setNextKeepAlive()
96
- setNextKeepAlive = =>
97
- @keepaliveTimeout = setTimeout doPing, KEEPALIVE_PING_TIMEOUT
98
- @_clearKeepalive()
99
- setNextKeepAlive()
100
-
101
- _clearKeepalive: =>
102
- if @keepaliveTimeout?
103
- clearTimeout @keepaliveTimeout
104
- @keepaliveTimeout = null
105
-
106
- class Firehose.MultiplexedWebSocket extends Firehose.WebSocket
107
- constructor: (args) ->
108
- super args
109
-
110
- subscribe: (channel, opts) =>
111
- @_sendMessage
112
- multiplex_subscribe:
113
- channel: channel
114
- message_sequence: opts.last_sequence
115
-
116
- unsubscribe: (channelNames...) =>
117
- @_sendMessage
118
- multiplex_unsubscribe: channelNames
119
-
120
- getLastMessageSequence: =>
121
- @_lastMessageSequence or {}
122
-
123
- _open: =>
124
- super()
125
- for channel, opts of @config.channels
126
- if @_lastMessageSequence
127
- opts.last_sequence = @_lastMessageSequence[channel]
128
-
129
- unless opts.last_sequence
130
- opts.last_sequence = 0
131
-
132
- @subscribe channel, opts
133
-
134
- _message: (event) =>
135
- frame = @config.parse event.data
136
- @_restartKeepAlive()
137
- unless isPong frame
138
- try
139
- @_lastMessageSequence ||= {}
140
- @_lastMessageSequence[frame.channel] = frame.last_sequence
141
- @config.message frame
142
- catch e
143
-
144
- sendPing = (socket) ->
145
- socket.send JSON.stringify ping: 'PING'
146
-
147
- isPong = (o) ->
148
- o.pong is 'PONG'
@@ -1,2 +0,0 @@
1
- #= require firehose/core
2
- #= require firehose/version
@@ -1,56 +0,0 @@
1
- require 'sprockets'
2
-
3
- module Firehose
4
- # Deal with bundling Sprocket assets into environments (like Rails or Sprockets)
5
- module Assets
6
- def self.path(*segs)
7
- File.join File.expand_path('../../assets', __FILE__), segs
8
- end
9
-
10
- # Integrate Firehose ./lib/assets files into a sprocket-enabled environment.
11
- module Sprockets
12
- # Entry-point Javascript for Sprockets project.
13
- JAVASCRIPT = "firehose.js"
14
-
15
- # Drop flash and javascript paths to Firehose assets into a sprockets environment.
16
- def self.configure(env)
17
- env.append_path Firehose::Assets.path('javascripts')
18
- env
19
- end
20
-
21
- # The "main" javascript that folks should compile and use in their
22
- # web applications.
23
- def self.javascript
24
- Firehose::Assets::Sprockets.environment[JAVASCRIPT].source
25
- end
26
-
27
- # Return a new sprockets environment configured with Firehose.
28
- def self.environment
29
- configure ::Sprockets::Environment.new
30
- end
31
-
32
- # Quick and dirty way for folks to compile the Firehose assets to a path
33
- # from the CLI and use. These are usualy non-ruby (or non-sprockets) folks
34
- # who want to run the firehose process and use the JS in a web app.
35
- def self.manifest(directory)
36
- ::Sprockets::Manifest.new(environment, directory)
37
- end
38
-
39
- # Try to automatically configure Sprockets if it's detected in the project.
40
- def self.auto_detect
41
- if defined? ::Sprockets and ::Sprockets.respond_to? :append_path
42
- Firehose::Assets::Sprockets.configure ::Sprockets
43
- end
44
- end
45
-
46
- def self.manifest_paths
47
- paths = []
48
- paths << File.basename(Firehose::Assets.path('/javascripts/firehose/firehose.js.coffee'), '.coffee')
49
- paths
50
- end
51
- end
52
- end
53
- end
54
-
55
- # Detect if Sprockets is loaded. If it is, lets configure Firehose to use it!
56
- Firehose::Assets::Sprockets.auto_detect
data/lib/firehose/cli.rb DELETED
@@ -1,79 +0,0 @@
1
- require 'thor'
2
- require 'eventmachine'
3
- require 'uri'
4
-
5
- # Enable native async-io libs
6
- EM.kqueue if EM.kqueue?
7
- EM.epoll if EM.epoll?
8
-
9
- module Firehose
10
- class CLI < Thor
11
- def initialize(*args)
12
- super
13
- # Disable buffering to $stdio for Firehose.logger
14
- $stdout.sync = true
15
- end
16
-
17
- desc "javascript", "Compile the Firehose JavaScript."
18
- def javascript
19
- $stderr.puts "DEPRECATION WARNING: Firehose JS assets have been moved to https://github.com/firehoseio/js_client"
20
- $stdout.puts Firehose::Assets::Sprockets.javascript
21
- end
22
-
23
- desc "version", "Display the current version."
24
- def version
25
- puts %[Firehose #{Firehose::VERSION} "#{Firehose::CODENAME}"]
26
- end
27
-
28
- desc "server", "Start an instance of a server."
29
- method_option :port, :type => :numeric, :default => ENV['PORT'] || Firehose::URI.port, :required => false, :aliases => '-p'
30
- method_option :host, :type => :string, :default => ENV['HOST'] || Firehose::URI.host, :required => false, :aliases => '-h'
31
- method_option :server, :type => :string, :default => ENV['SERVER'] ||'rainbows', :required => false, :aliases => '-s'
32
- def server
33
- begin
34
- Firehose::Server::App.new(options).start
35
- rescue => e
36
- Firehose.logger.error "#{e.message}: #{e.backtrace}"
37
- raise e
38
- end
39
- end
40
-
41
- desc "consume URI", "Consume messages from a resource."
42
- method_option :concurrency, :type => :numeric, :default => 1, :aliases => '-c'
43
- def consume(uri)
44
- EM.run do
45
- options[:concurrency].times { Firehose::Client::Consumer.parse(uri).request }
46
- end
47
- end
48
-
49
- desc "publish URI [PAYLOAD]", "Publish messages to a resource."
50
- method_option :ttl, :type => :numeric, :aliases => '-t'
51
- method_option :times, :type => :numeric, :aliases => '-n', :default => 1
52
- method_option :interval, :type => :numeric, :aliases => '-i'
53
- def publish(uri, payload=nil)
54
- payload ||= $stdin.read
55
- client = Firehose::Client::Producer::Http.new(uri)
56
- path = ::URI.parse(uri).path
57
- times = options[:times]
58
- ttl = options[:ttl]
59
-
60
- EM.run do
61
- # TODO I think this can be cleaned up so the top-level if/else can be ditched.
62
- if interval = options[:interval]
63
- # Publish messages at a forced interval.
64
- EM.add_periodic_timer interval do
65
- client.publish(payload).to(path, :ttl => ttl)
66
- EM.stop if times && (times-=1).zero?
67
- end
68
- else
69
- # Publish messages as soon as the last message was published.
70
- worker = Proc.new do
71
- client.publish(payload).to(path, :ttl => ttl)
72
- times && (times-=1).zero? ? EM.stop : worker.call
73
- end
74
- worker.call
75
- end
76
- end
77
- end
78
- end
79
- end