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.
- data/README.rdoc +25 -1
- data/lib/bayeux.rb +32 -18
- 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
|
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.
|
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
|
-
|
90
|
-
|
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
|
-
|
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
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
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
|
-
|
326
|
-
|
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:
|
4
|
+
hash: 5
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
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-
|
18
|
+
date: 2011-07-28 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: json
|