bayeux-rack 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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