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.
- 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
|