firehose 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec CHANGED
@@ -1 +1 @@
1
- --colour
1
+ --colour
data/README.md CHANGED
@@ -65,14 +65,14 @@ You have a dirt simple HTTP pub-sub feed. You could setup an `after_commit` hook
65
65
 
66
66
  Holy mackerel! Its a nice, clean, RESTful way to build real-time web applications.
67
67
 
68
- # The JavaScript Client
68
+ # The JavaScript Consumer
69
69
 
70
70
  Firehose doesn't just stop at curl; it has a full-featured JavaScript client that lets you subscribe to channels for live updates.
71
71
 
72
72
  Still have the server running? Copy and paste the code below into Firebug or the WebKit console.
73
73
 
74
74
  ```javascript
75
- new Firehose.Client({
75
+ new Firehose.Consumer({
76
76
  message: function(msg){
77
77
  console.log(msg);
78
78
  },
data/firehose.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.version = Firehose::VERSION
8
8
  s.authors = ["Brad Gessler", "Steel Fu"]
9
9
  s.email = ["brad@polleverywhere.com", "steel@polleverywhere.com"]
10
- s.homepage = "http://github.com/polleverywhere/firehose"
10
+ s.homepage = "http://firehose.io/"
11
11
  s.summary = %q{Build realtime Ruby web applications}
12
12
  s.description = %q{Firehose is a realtime web application toolkit for building realtime Ruby web applications.}
13
13
 
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.add_runtime_dependency "thin"
25
25
  s.add_runtime_dependency "thor"
26
26
  s.add_runtime_dependency "websocket-rack"
27
+ s.add_runtime_dependency "faraday"
27
28
 
28
29
  s.add_development_dependency "rspec"
29
30
  s.add_development_dependency "rack-test"
@@ -2,4 +2,4 @@
2
2
  #= require firehose/transport
3
3
  #= require firehose/long_poll
4
4
  #= require firehose/web_socket
5
- #= require firehose/client
5
+ #= require firehose/consumer
@@ -0,0 +1,61 @@
1
+ class Firehose.Consumer
2
+ # Transports that are available to Firehose.
3
+ @transports: [Firehose.WebSocket, Firehose.LongPoll]
4
+
5
+ # Generate a random consumer id.
6
+ @nextConsumerId: ->
7
+ Math.floor((Math.random()*99999999999)+1)
8
+
9
+ constructor: (config = {}) ->
10
+ # The consumerId is used by the server to remember messages between requests. In a production environment,
11
+ # this should probably be some combination of "user_id-rand". Why the rand? Because a user may have multiple
12
+ # tabs open to the application, and each tab needs a different channel on the server.
13
+ config.consumerId ||= Firehose.Consumer.nextConsumerId()
14
+ # List of transport stragies we have to use.
15
+ config.transports ||= Firehose.Consumer.transports
16
+ # Empty handler for messages.
17
+ config.message ||= ->
18
+ # Empty handler for error handling.
19
+ config.error ||= ->
20
+ # Empty handler for when we establish a connection.
21
+ config.connected ||= ->
22
+ # Empty handler for when we're disconnected.
23
+ config.disconnected ||= ->
24
+ # The initial connection failed. This is probably triggered when a transport, like WebSockets
25
+ # is supported by the browser, but for whatever reason it can't connect (probably a firewall)
26
+ config.failed ||= ->
27
+ throw "Could not connect"
28
+ # URL that we'll connect to.
29
+ config.uri ||= undefined
30
+ # Params that we'll tack on to the URL. We include a consumerId in here for kicks.
31
+ config.params ||= { cid: config.consumerId }
32
+ # Do stuff before we send the message into config.message. The sensible
33
+ # default on the webs is to parse JSON.
34
+ config.parse ||= (body) ->
35
+ $.parseJSON(body)
36
+
37
+ # Hang on to these config for when we connect.
38
+ @config = config
39
+ # Make sure we return ourself out of the constructor so we can chain.
40
+ this
41
+
42
+ connect: =>
43
+ # Get a list of transports that the browser supports
44
+ supportedTransports = (transport for transport in @config.transports when transport.supported())
45
+ # Mmmkay, we've got transports supported by the browser, now lets try connecting
46
+ # to them and dealing with failed connections that might be caused by firewalls,
47
+ # or other network connectivity issues.
48
+ transports = for transport in supportedTransports
49
+ # Copy the config so we can modify it with a failed callback.
50
+ config = @config
51
+ # Map the next transport into the existing transports connectionError
52
+ # If the connection fails, try the next transport supported by the browser.
53
+ config.failed = =>
54
+ # Map the next transport to connect insie of the current transport failures
55
+ if nextTransport = supportedTransports.pop()
56
+ new nextTransport(config).connect()
57
+ else
58
+ @config.failed() # Call the original fail method passed into the Firehose.Consumer
59
+ new transport(config)
60
+ # Fire off the first connection attempt.
61
+ transports[0].connect()
@@ -14,10 +14,14 @@ class Firehose.LongPoll extends Firehose.Transport
14
14
  @config.longPoll ||= {}
15
15
  # Protocol schema we should use for talking to WS server.
16
16
  @config.longPoll.url ||= "http:#{@config.uri}"
17
+ # How many ms should we wait before timing out the AJAX connection?
18
+ # TODO why was this set at 0s?
19
+ @config.longPoll.timeout ||= 0
17
20
 
21
+ # TODO - What is @_lagTime for? Can't we just use the @_timeout value?
18
22
  # We use the lag time to make the client live longer than the server.
19
23
  @_lagTime = 5000
20
- @_timeout = @config.options.timeout + @_lagTime
24
+ @_timeout = @config.longPoll.timeout + @_lagTime
21
25
  @_offlineTimer
22
26
  @_okInterval = 0
23
27
 
@@ -63,6 +67,10 @@ class Firehose.LongPoll extends Firehose.Transport
63
67
  error: @_error
64
68
 
65
69
  _success: (data, status, jqXhr) =>
70
+ # TODO we actually want to do this when the thing calls out... mmm right now it takes
71
+ # up to 30s before we can call this thing.
72
+ # Call the 'connected' callback if the connection succeeds.
73
+ @_open(data) unless @_succeeded
66
74
  if jqXhr.status == 204
67
75
  # If we get a 204 back, that means the server timed-out and sent back a 204 with a
68
76
  # X-Http-Next-Request header
@@ -21,12 +21,17 @@ class Firehose.Transport
21
21
 
22
22
  # Default error handler
23
23
  _error: (event) =>
24
- # Lets try to connect again with delay
25
- @config.disconnected()
26
- @connect(@_retryDelay)
24
+ unless @_succeeded
25
+ # Fail peremantly if the error happens on the first connection.
26
+ @config.failed(this)
27
+ else
28
+ # Lets try to connect again with delay
29
+ @config.disconnected()
30
+ @connect(@_retryDelay)
27
31
 
28
32
  # Default connection established handler
29
33
  _open: (event) =>
34
+ @_succeeded = true
30
35
  @config.connected()
31
36
 
32
37
  # Default connection closed handler
@@ -5,7 +5,7 @@ class Firehose.WebSocket extends Firehose.Transport
5
5
  @supported: =>
6
6
  # Compatibility reference: http://caniuse.com/websockets
7
7
  # Native websocket support + Flash web socket
8
- window.WebSocket || (window["MozWebSocket"] and window.MozWebSocket) || WebSocket.flashSupported()
8
+ !!(window.WebSocket || (window["MozWebSocket"] and window.MozWebSocket) || WebSocket.flashSupported())
9
9
 
10
10
  constructor: (args) ->
11
11
  super args
data/lib/firehose/rack.rb CHANGED
@@ -95,10 +95,18 @@ module Firehose
95
95
 
96
96
  class App
97
97
  def call(env)
98
- websocket_request?(env) ? WebSocket.new.call(env) : HttpLongPoll.new.call(env)
98
+ websocket_request?(env) ? websocket.call(env) : http_long_poll.call(env)
99
99
  end
100
100
 
101
101
  private
102
+ def websocket
103
+ @websocket ||= WebSocket.new
104
+ end
105
+
106
+ def http_long_poll
107
+ @http_long_poll ||= HttpLongPoll.new
108
+ end
109
+
102
110
  def websocket_request?(env)
103
111
  env['HTTP_UPGRADE'] =~ /websocket/i
104
112
  end
@@ -1,4 +1,4 @@
1
1
  module Firehose
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  CODENAME = "Garden Hose"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firehose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-04-27 00:00:00.000000000 Z
13
+ date: 2012-04-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: eventmachine
17
- requirement: &70248633218840 !ruby/object:Gem::Requirement
17
+ requirement: &70248892020200 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 1.0.0.beta
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70248633218840
25
+ version_requirements: *70248892020200
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: amqp
28
- requirement: &70248633201380 !ruby/object:Gem::Requirement
28
+ requirement: &70248892017640 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 0.9.4
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70248633201380
36
+ version_requirements: *70248892017640
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: thin
39
- requirement: &70248633200480 !ruby/object:Gem::Requirement
39
+ requirement: &70248892031220 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70248633200480
47
+ version_requirements: *70248892031220
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: thor
50
- requirement: &70248633199280 !ruby/object:Gem::Requirement
50
+ requirement: &70248892024520 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70248633199280
58
+ version_requirements: *70248892024520
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: websocket-rack
61
- requirement: &70248633198520 !ruby/object:Gem::Requirement
61
+ requirement: &70248892039500 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,21 @@ dependencies:
66
66
  version: '0'
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *70248633198520
69
+ version_requirements: *70248892039500
70
+ - !ruby/object:Gem::Dependency
71
+ name: faraday
72
+ requirement: &70248892037240 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: *70248892037240
70
81
  - !ruby/object:Gem::Dependency
71
82
  name: rspec
72
- requirement: &70248633197580 !ruby/object:Gem::Requirement
83
+ requirement: &70248892032840 !ruby/object:Gem::Requirement
73
84
  none: false
74
85
  requirements:
75
86
  - - ! '>='
@@ -77,10 +88,10 @@ dependencies:
77
88
  version: '0'
78
89
  type: :development
79
90
  prerelease: false
80
- version_requirements: *70248633197580
91
+ version_requirements: *70248892032840
81
92
  - !ruby/object:Gem::Dependency
82
93
  name: rack-test
83
- requirement: &70248633196960 !ruby/object:Gem::Requirement
94
+ requirement: &70248892042160 !ruby/object:Gem::Requirement
84
95
  none: false
85
96
  requirements:
86
97
  - - ! '>='
@@ -88,10 +99,10 @@ dependencies:
88
99
  version: '0'
89
100
  type: :development
90
101
  prerelease: false
91
- version_requirements: *70248633196960
102
+ version_requirements: *70248892042160
92
103
  - !ruby/object:Gem::Dependency
93
104
  name: guard-rspec
94
- requirement: &70248633195800 !ruby/object:Gem::Requirement
105
+ requirement: &70248892053200 !ruby/object:Gem::Requirement
95
106
  none: false
96
107
  requirements:
97
108
  - - ! '>='
@@ -99,10 +110,10 @@ dependencies:
99
110
  version: '0'
100
111
  type: :development
101
112
  prerelease: false
102
- version_requirements: *70248633195800
113
+ version_requirements: *70248892053200
103
114
  - !ruby/object:Gem::Dependency
104
115
  name: guard-bundler
105
- requirement: &70248633195200 !ruby/object:Gem::Requirement
116
+ requirement: &70248892049780 !ruby/object:Gem::Requirement
106
117
  none: false
107
118
  requirements:
108
119
  - - ! '>='
@@ -110,10 +121,10 @@ dependencies:
110
121
  version: '0'
111
122
  type: :development
112
123
  prerelease: false
113
- version_requirements: *70248633195200
124
+ version_requirements: *70248892049780
114
125
  - !ruby/object:Gem::Dependency
115
126
  name: em-http-request
116
- requirement: &70248633178620 !ruby/object:Gem::Requirement
127
+ requirement: &70248892059480 !ruby/object:Gem::Requirement
117
128
  none: false
118
129
  requirements:
119
130
  - - ~>
@@ -121,10 +132,10 @@ dependencies:
121
132
  version: 0.3.0
122
133
  type: :development
123
134
  prerelease: false
124
- version_requirements: *70248633178620
135
+ version_requirements: *70248892059480
125
136
  - !ruby/object:Gem::Dependency
126
137
  name: guard-coffeescript
127
- requirement: &70248633177760 !ruby/object:Gem::Requirement
138
+ requirement: &70248892071480 !ruby/object:Gem::Requirement
128
139
  none: false
129
140
  requirements:
130
141
  - - ! '>='
@@ -132,7 +143,7 @@ dependencies:
132
143
  version: '0'
133
144
  type: :development
134
145
  prerelease: false
135
- version_requirements: *70248633177760
146
+ version_requirements: *70248892071480
136
147
  description: Firehose is a realtime web application toolkit for building realtime
137
148
  Ruby web applications.
138
149
  email:
@@ -156,7 +167,7 @@ files:
156
167
  - lib/assets/flash/firehose/WebSocketMain.swf
157
168
  - lib/assets/javascripts/firehose.js.coffee
158
169
  - lib/assets/javascripts/firehose/base.js.coffee
159
- - lib/assets/javascripts/firehose/client.js.coffee
170
+ - lib/assets/javascripts/firehose/consumer.js.coffee
160
171
  - lib/assets/javascripts/firehose/long_poll.js.coffee
161
172
  - lib/assets/javascripts/firehose/transport.js.coffee
162
173
  - lib/assets/javascripts/firehose/web_socket.js.coffee
@@ -170,7 +181,7 @@ files:
170
181
  - spec/integrations/amqp_resources_spec.rb
171
182
  - spec/integrations/thin_spec.rb
172
183
  - spec/spec_helper.rb
173
- homepage: http://github.com/polleverywhere/firehose
184
+ homepage: http://firehose.io/
174
185
  licenses: []
175
186
  post_install_message:
176
187
  rdoc_options: []
@@ -1,45 +0,0 @@
1
- class Firehose.Client
2
- # Transports that are available to Firehose.
3
- @transports: ['WebSocket', 'LongPoll']
4
-
5
- # Generate a random client_id.
6
- @nextClientId: ->
7
- Math.floor((Math.random()*99999999999)+1)
8
-
9
- constructor: (config={}) ->
10
- # The clientId is used by the server to remember messages between requests. In a production environment,
11
- # this should probably be some combination of "user_id-rand". Why the rand? Because a user may have multiple
12
- # tabs open to the application, and each tab needs a different channel on the server.
13
- config.clientId ||= Firehose.Client.nextClientId()
14
- # List of transport stragies we have to use.
15
- config.transports ||= Firehose.Client.transports
16
- # Empty handler for messages.
17
- config.message ||= ->
18
- # Empty handler for error handling.
19
- config.error ||= ->
20
- # Empty handler for when we establish a connection.
21
- config.connected ||= ->
22
- # Empty handler for when we're disconnected.
23
- config.disconnected ||= ->
24
- # Additional options.
25
- config.options ||= {}
26
- # URL that we'll connect to.
27
- config.uri ||= undefined
28
- # Params that we'll tack on to the URL. We include a clientId in here for kicks.
29
- config.params ||= { cid: config.clientId }
30
- # Do stuff before we send the message into config.message. The sensible
31
- # default on the webs is to parse JSON.
32
- config.parse ||= (body) ->
33
- $.parseJSON(body)
34
-
35
- # Hang on to these config for when we connect.
36
- @config = config
37
- # Make sure we return ourself out of the constructor so we can chain.
38
- this
39
-
40
- connect: =>
41
- # Figure out what transport is supported and return it.
42
- # TODO if the initial connection fails, try the next transport mmmkay?
43
- for transport in @config.transports
44
- if transport = Firehose[transport]
45
- return new transport(@config).connect() if transport.supported()