bayeux-rack 0.6.0 → 0.6.1

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 (3) hide show
  1. data/README.rdoc +25 -1
  2. data/lib/bayeux.rb +32 -18
  3. metadata +4 -4
data/README.rdoc CHANGED
@@ -7,18 +7,42 @@ asynchronous Rack extensions added to Thin by async_sinatra.
7
7
  Because it uses async_sinatra, which uses EventMachine, it won't work in Passenger.
8
8
  Sorry about that, but Apache doesn't really like long-polling anyhow. Use Thin.
9
9
 
10
+ You can see a video presentation of this code here:
11
+ http://www.youtube.com/watch?v=Bhj9QOfNd4c
12
+
10
13
  == Usage
11
14
 
12
15
  See http://github.com/cjheath/jquery.comet
13
16
  for an example of usage and for a COMET client in Javascript.
14
17
 
18
+ class MyServer < Bayeux
19
+ configure do
20
+ # The default :public is inside the Bayeux gem
21
+ set :public, File.dirname(__FILE__)
22
+ end
23
+
24
+ def deliver message
25
+ case channel_name = message['channel']
26
+ when '/my/interesting/channel'
27
+ data = message['data']
28
+ if data == 'ping'
29
+ publish :channel => channel_name, :data => 'pong'
30
+ else
31
+ super
32
+ end
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+
15
39
  == Installing
16
40
 
17
41
  gem install bayeux-rack
18
42
 
19
43
  == License
20
44
 
21
- The jquery.comet.js and chat_server are subject to the MIT license.
45
+ The MIT license.
22
46
 
23
47
  == Developing
24
48
 
data/lib/bayeux.rb CHANGED
@@ -14,7 +14,7 @@ require 'eventmachine'
14
14
  # implementing the COMET protocol.
15
15
  class Bayeux < Sinatra::Base
16
16
  # The Gem version of this implementation
17
- VERSION = "0.6.0"
17
+ VERSION = "0.6.1"
18
18
  register Sinatra::Async
19
19
 
20
20
  # A connected client
@@ -86,8 +86,11 @@ class Bayeux < Sinatra::Base
86
86
 
87
87
  # ClientIds should be strong random numbers containing at least 128 bits of entropy. These aren't!
88
88
  def next_client_id
89
- @@next_client_id ||= 0
90
- (@@next_client_id += 1).to_s
89
+ begin
90
+ id = (rand*1_000_000_000).to_i
91
+ end until !clients[id]
92
+ trace "New client recieves ID #{id}"
93
+ id
91
94
  end
92
95
 
93
96
  # Send a message (a Hash) to a channel.
@@ -243,6 +246,7 @@ class Bayeux < Sinatra::Base
243
246
  if !queued.empty? || client.subscription
244
247
  if client.subscription
245
248
  # If the client opened a second long-poll, finish that one and this:
249
+ trace "Another long-poll seems to be already active for #{clientId}; close it!"
246
250
  client.channel.push true # Complete the outstanding poll
247
251
  end
248
252
  client.queue << connect_response
@@ -253,7 +257,9 @@ class Bayeux < Sinatra::Base
253
257
  client.subscription =
254
258
  client.channel.subscribe do |msg|
255
259
  queued = client.queue
256
- trace "Client #{clientId} awoke but found an empty queue" if queued.empty?
260
+ if queued.empty?
261
+ trace "Client #{clientId} awoke but found an empty queue"
262
+ end
257
263
  client.queue << connect_response
258
264
  client.flush(self)
259
265
  end
@@ -309,22 +315,30 @@ class Bayeux < Sinatra::Base
309
315
 
310
316
  # Parse a message (or array of messages) from an HTTP request and deliver the messages
311
317
  def receive message_json
312
- message = JSON.parse(message_json)
313
-
314
- # The message here should either be a connect message (long-poll) or messages being sent.
315
- # For a long-poll we return a reponse immediately only if messages are queued for this client.
316
- # For a send-message, we always return a response immediately, even if it's just an acknowledgement.
317
- @is_connect = false
318
- response = deliver_all(message)
319
- return if @is_connect
320
-
321
- if clientId = params['clientId'] and client = clients[clientId]
322
- client.queue += response
323
- client.flush if params['jsonp'] || !client.queue.empty?
318
+ message = [JSON.parse(message_json)].flatten
319
+
320
+ clientId = message[0]['clientId']
321
+ channel_name = message[0]['channel']
322
+ if (channel_name == '/meta/handshake' && message.size == 1)
323
+ respond(deliver(message[0]))
324
324
  else
325
- # No client so no queue. Respond immediately if we can, else long-poll
326
- respond(response) unless response.empty?
325
+ client = clients[clientId]
326
+ if (!client)
327
+ respond([{:advice => {:reconnect => :handshake}}])
328
+ else
329
+ # The message here should either be a connect message (long-poll) or messages being sent.
330
+ # For a long-poll we return a reponse immediately only if messages are queued for this client.
331
+ # For a send-message, we always return a response immediately, even if it's just an acknowledgement.
332
+ @is_connect = false
333
+ response = deliver_all(message)
334
+ if @is_connect # A long poll
335
+ return
336
+ end
337
+ client.queue += response
338
+ client.flush if params['jsonp'] || !client.queue.empty?
339
+ end
327
340
  end
341
+
328
342
  rescue => e
329
343
  respond([])
330
344
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bayeux-rack
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 0
10
- version: 0.6.0
9
+ - 1
10
+ version: 0.6.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Clifford Heath
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-17 00:00:00 Z
18
+ date: 2011-07-28 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: json