message_bus 0.0.2 → 0.9.3
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.
Potentially problematic release.
This version of message_bus might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.travis.yml +6 -0
- data/CHANGELOG +9 -0
- data/Gemfile +15 -0
- data/Guardfile +7 -0
- data/README.md +8 -0
- data/Rakefile +14 -0
- data/assets/application.handlebars +7 -0
- data/assets/application.js +79 -0
- data/assets/ember.js +26839 -0
- data/assets/handlebars.js +2201 -0
- data/assets/index.handlebars +25 -0
- data/assets/jquery-1.8.2.js +9440 -0
- data/assets/message-bus.js +247 -0
- data/examples/bench/ab.sample +1 -0
- data/examples/bench/config.ru +24 -0
- data/examples/bench/payload.post +1 -0
- data/examples/bench/unicorn.conf.rb +4 -0
- data/examples/chat/chat.rb +74 -0
- data/examples/chat/config.ru +2 -0
- data/lib/message_bus.rb +60 -5
- data/lib/message_bus/client.rb +45 -7
- data/lib/message_bus/connection_manager.rb +35 -7
- data/lib/message_bus/em_ext.rb +5 -0
- data/lib/message_bus/rack/middleware.rb +60 -89
- data/lib/message_bus/rack/thin_ext.rb +71 -0
- data/lib/message_bus/rails/railtie.rb +4 -1
- data/lib/message_bus/reliable_pub_sub.rb +22 -4
- data/lib/message_bus/version.rb +1 -1
- data/message_bus.gemspec +20 -0
- data/spec/lib/client_spec.rb +50 -0
- data/spec/lib/connection_manager_spec.rb +83 -0
- data/spec/lib/fake_async_middleware.rb +134 -0
- data/spec/lib/handlers/demo_message_handler.rb +5 -0
- data/spec/lib/message_bus_spec.rb +112 -0
- data/spec/lib/message_handler_spec.rb +39 -0
- data/spec/lib/middleware_spec.rb +306 -0
- data/spec/lib/multi_process_spec.rb +60 -0
- data/spec/lib/reliable_pub_sub_spec.rb +167 -0
- data/spec/spec_helper.rb +19 -0
- data/vendor/assets/javascripts/message-bus.js +247 -0
- metadata +55 -26
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'message_bus'
|
3
|
+
|
4
|
+
describe MessageBus::MessageHandler do
|
5
|
+
|
6
|
+
it "should properly register message handlers" do
|
7
|
+
MessageBus::MessageHandler.handle "/hello" do |m|
|
8
|
+
m
|
9
|
+
end
|
10
|
+
MessageBus::MessageHandler.call("site","/hello", "world", 1).should == "world"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should correctly load message handlers" do
|
14
|
+
MessageBus::MessageHandler.load_handlers("#{File.dirname(__FILE__)}/handlers")
|
15
|
+
MessageBus::MessageHandler.call("site","/dupe", "1", 1).should == "11"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow for a connect / disconnect callback" do
|
19
|
+
MessageBus::MessageHandler.handle "/channel" do |m|
|
20
|
+
m
|
21
|
+
end
|
22
|
+
|
23
|
+
connected = false
|
24
|
+
disconnected = false
|
25
|
+
|
26
|
+
MessageBus.on_connect do |site_id|
|
27
|
+
connected = true
|
28
|
+
end
|
29
|
+
MessageBus.on_disconnect do |site_id|
|
30
|
+
disconnected = true
|
31
|
+
end
|
32
|
+
|
33
|
+
MessageBus::MessageHandler.call("site_id", "/channel", "data", 1)
|
34
|
+
|
35
|
+
connected.should == true
|
36
|
+
disconnected.should == true
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,306 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'message_bus'
|
5
|
+
require 'rack/test'
|
6
|
+
|
7
|
+
describe MessageBus::Rack::Middleware do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
before do
|
11
|
+
MessageBus.long_polling_enabled = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def app
|
15
|
+
@app ||= Rack::Builder.new {
|
16
|
+
use FakeAsyncMiddleware
|
17
|
+
use MessageBus::Rack::Middleware
|
18
|
+
run lambda {|env| [500, {'Content-Type' => 'text/html'}, 'should not be called' ]}
|
19
|
+
}.to_app
|
20
|
+
end
|
21
|
+
|
22
|
+
shared_examples "long polling" do
|
23
|
+
before do
|
24
|
+
MessageBus.long_polling_enabled = true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should respond right away if dlp=t" do
|
28
|
+
post "/message-bus/ABC?dlp=t", '/foo1' => 0
|
29
|
+
FakeAsyncMiddleware.in_async?.should == false
|
30
|
+
last_response.should be_ok
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should respond right away to long polls that are polling on -1 with the last_id" do
|
34
|
+
post "/message-bus/ABC", '/foo' => -1
|
35
|
+
last_response.should be_ok
|
36
|
+
parsed = JSON.parse(last_response.body)
|
37
|
+
parsed.length.should == 1
|
38
|
+
parsed[0]["channel"].should == "/__status"
|
39
|
+
parsed[0]["data"]["/foo"].should == MessageBus.last_id("/foo")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should respond to long polls when data is available" do
|
43
|
+
|
44
|
+
Thread.new do
|
45
|
+
wait_for(2000) { FakeAsyncMiddleware.in_async? }
|
46
|
+
MessageBus.publish "/foo", "םוֹלשָׁ"
|
47
|
+
end
|
48
|
+
|
49
|
+
post "/message-bus/ABC", '/foo' => nil
|
50
|
+
|
51
|
+
last_response.should be_ok
|
52
|
+
parsed = JSON.parse(last_response.body)
|
53
|
+
parsed.length.should == 1
|
54
|
+
parsed[0]["data"].should == "םוֹלשָׁ"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should timeout within its alloted slot" do
|
58
|
+
begin
|
59
|
+
MessageBus.long_polling_interval = 10
|
60
|
+
s = Time.now.to_f * 1000
|
61
|
+
post "/message-bus/ABC", '/foo' => nil
|
62
|
+
(Time.now.to_f * 1000 - s).should < 30
|
63
|
+
ensure
|
64
|
+
MessageBus.long_polling_interval = 5000
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should support batch filtering" do
|
69
|
+
MessageBus.user_id_lookup do |env|
|
70
|
+
1
|
71
|
+
end
|
72
|
+
|
73
|
+
MessageBus.around_client_batch("/demo") do |message, user_ids, callback|
|
74
|
+
begin
|
75
|
+
Thread.current["test"] = user_ids
|
76
|
+
callback.call
|
77
|
+
ensure
|
78
|
+
Thread.current["test"] = nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
test = nil
|
83
|
+
|
84
|
+
MessageBus.client_filter("/demo") do |user_id, message|
|
85
|
+
test = Thread.current["test"]
|
86
|
+
message
|
87
|
+
end
|
88
|
+
|
89
|
+
client_id = "ABCD"
|
90
|
+
|
91
|
+
id = MessageBus.publish("/demo", "test")
|
92
|
+
|
93
|
+
Thread.new do
|
94
|
+
wait_for(2000) { FakeAsyncMiddleware.in_async? }
|
95
|
+
MessageBus.publish "/demo", "test"
|
96
|
+
end
|
97
|
+
|
98
|
+
post "/message-bus/#{client_id}", {
|
99
|
+
'/demo' => id
|
100
|
+
}
|
101
|
+
|
102
|
+
test.should == [1]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "thin async" do
|
107
|
+
before do
|
108
|
+
FakeAsyncMiddleware.simulate_thin_async
|
109
|
+
end
|
110
|
+
it_behaves_like "long polling"
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "hijack" do
|
114
|
+
before do
|
115
|
+
FakeAsyncMiddleware.simulate_hijack
|
116
|
+
MessageBus.rack_hijack_enabled = true
|
117
|
+
end
|
118
|
+
it_behaves_like "long polling"
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "diagnostics" do
|
122
|
+
|
123
|
+
it "should return a 403 if a user attempts to get at the _diagnostics path" do
|
124
|
+
get "/message-bus/_diagnostics"
|
125
|
+
last_response.status.should == 403
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should get a 200 with html for an authorized user" do
|
129
|
+
MessageBus.stub(:is_admin_lookup).and_return(lambda{|env| true })
|
130
|
+
get "/message-bus/_diagnostics"
|
131
|
+
last_response.status.should == 200
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should get the script it asks for" do
|
135
|
+
MessageBus.stub(:is_admin_lookup).and_return(lambda{|env| true })
|
136
|
+
get "/message-bus/_diagnostics/assets/message-bus.js"
|
137
|
+
last_response.status.should == 200
|
138
|
+
last_response.content_type.should == "text/javascript;"
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "polling" do
|
144
|
+
before do
|
145
|
+
MessageBus.long_polling_enabled = false
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should respond with a 200 to a subscribe" do
|
149
|
+
client_id = "ABCD"
|
150
|
+
|
151
|
+
# client always keeps a list of channels with last message id they got on each
|
152
|
+
post "/message-bus/#{client_id}", {
|
153
|
+
'/foo' => nil,
|
154
|
+
'/bar' => nil
|
155
|
+
}
|
156
|
+
last_response.should be_ok
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should correctly understand that -1 means stuff from now onwards" do
|
160
|
+
|
161
|
+
MessageBus.publish('foo', 'bar')
|
162
|
+
|
163
|
+
post "/message-bus/ABCD", {
|
164
|
+
'/foo' => -1
|
165
|
+
}
|
166
|
+
last_response.should be_ok
|
167
|
+
parsed = JSON.parse(last_response.body)
|
168
|
+
parsed.length.should == 1
|
169
|
+
parsed[0]["channel"].should == "/__status"
|
170
|
+
parsed[0]["data"]["/foo"].should == MessageBus.last_id("/foo")
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should respond with the data if messages exist in the backlog" do
|
175
|
+
id = MessageBus.last_id('/foo')
|
176
|
+
|
177
|
+
MessageBus.publish("/foo", "barbs")
|
178
|
+
MessageBus.publish("/foo", "borbs")
|
179
|
+
|
180
|
+
client_id = "ABCD"
|
181
|
+
post "/message-bus/#{client_id}", {
|
182
|
+
'/foo' => id,
|
183
|
+
'/bar' => nil
|
184
|
+
}
|
185
|
+
|
186
|
+
parsed = JSON.parse(last_response.body)
|
187
|
+
parsed.length.should == 2
|
188
|
+
parsed[0]["data"].should == "barbs"
|
189
|
+
parsed[1]["data"].should == "borbs"
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should not get consumed messages" do
|
193
|
+
MessageBus.publish("/foo", "barbs")
|
194
|
+
id = MessageBus.last_id('/foo')
|
195
|
+
|
196
|
+
client_id = "ABCD"
|
197
|
+
post "/message-bus/#{client_id}", {
|
198
|
+
'/foo' => id
|
199
|
+
}
|
200
|
+
|
201
|
+
parsed = JSON.parse(last_response.body)
|
202
|
+
parsed.length.should == 0
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should filter by user correctly" do
|
206
|
+
id = MessageBus.publish("/foo", "test", user_ids: [1])
|
207
|
+
MessageBus.user_id_lookup do |env|
|
208
|
+
0
|
209
|
+
end
|
210
|
+
|
211
|
+
client_id = "ABCD"
|
212
|
+
post "/message-bus/#{client_id}", {
|
213
|
+
'/foo' => id - 1
|
214
|
+
}
|
215
|
+
|
216
|
+
parsed = JSON.parse(last_response.body)
|
217
|
+
parsed.length.should == 0
|
218
|
+
|
219
|
+
MessageBus.user_id_lookup do |env|
|
220
|
+
1
|
221
|
+
end
|
222
|
+
|
223
|
+
post "/message-bus/#{client_id}", {
|
224
|
+
'/foo' => id - 1
|
225
|
+
}
|
226
|
+
|
227
|
+
parsed = JSON.parse(last_response.body)
|
228
|
+
parsed.length.should == 1
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
it "should filter by client_filter correctly" do
|
233
|
+
id = MessageBus.publish("/filter", "test")
|
234
|
+
user_id = 0
|
235
|
+
|
236
|
+
MessageBus.user_id_lookup do |env|
|
237
|
+
user_id
|
238
|
+
end
|
239
|
+
|
240
|
+
MessageBus.client_filter("/filter") do |user_id, message|
|
241
|
+
if user_id == 0
|
242
|
+
message = message.dup
|
243
|
+
message.data += "_filter"
|
244
|
+
message
|
245
|
+
elsif user_id == 1
|
246
|
+
message
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
client_id = "ABCD"
|
251
|
+
|
252
|
+
post "/message-bus/#{client_id}", {
|
253
|
+
'/filter' => id - 1
|
254
|
+
}
|
255
|
+
|
256
|
+
parsed = JSON.parse(last_response.body)
|
257
|
+
parsed[0]['data'].should == "test_filter"
|
258
|
+
|
259
|
+
user_id = 1
|
260
|
+
|
261
|
+
post "/message-bus/#{client_id}", {
|
262
|
+
'/filter' => id - 1
|
263
|
+
}
|
264
|
+
|
265
|
+
parsed = JSON.parse(last_response.body)
|
266
|
+
parsed.length.should == 1
|
267
|
+
parsed[0]["data"].should == "test"
|
268
|
+
|
269
|
+
user_id = 2
|
270
|
+
|
271
|
+
post "/message-bus/#{client_id}", {
|
272
|
+
'/filter' => id - 1
|
273
|
+
}
|
274
|
+
|
275
|
+
parsed = JSON.parse(last_response.body)
|
276
|
+
parsed.length.should == 0
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should filter by group correctly" do
|
280
|
+
id = MessageBus.publish("/foo", "test", group_ids: [3,4,5])
|
281
|
+
MessageBus.group_ids_lookup do |env|
|
282
|
+
[0,1,2]
|
283
|
+
end
|
284
|
+
|
285
|
+
client_id = "ABCD"
|
286
|
+
post "/message-bus/#{client_id}", {
|
287
|
+
'/foo' => id - 1
|
288
|
+
}
|
289
|
+
|
290
|
+
parsed = JSON.parse(last_response.body)
|
291
|
+
parsed.length.should == 0
|
292
|
+
|
293
|
+
MessageBus.group_ids_lookup do |env|
|
294
|
+
[1,7,4,100]
|
295
|
+
end
|
296
|
+
|
297
|
+
post "/message-bus/#{client_id}", {
|
298
|
+
'/foo' => id - 1
|
299
|
+
}
|
300
|
+
|
301
|
+
parsed = JSON.parse(last_response.body)
|
302
|
+
parsed.length.should == 1
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'message_bus'
|
3
|
+
|
4
|
+
describe MessageBus::ReliablePubSub do
|
5
|
+
|
6
|
+
def new_bus
|
7
|
+
MessageBus::ReliablePubSub.new(:db => 10)
|
8
|
+
end
|
9
|
+
|
10
|
+
def work_it
|
11
|
+
Signal.trap("HUP") { exit }
|
12
|
+
|
13
|
+
bus = new_bus
|
14
|
+
$stdout.reopen("/dev/null", "w")
|
15
|
+
$stderr.reopen("/dev/null", "w")
|
16
|
+
# subscribe blocks, so we need a new bus to transmit
|
17
|
+
new_bus.subscribe("/echo", 0) do |msg|
|
18
|
+
bus.publish("/response", Process.pid.to_s)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def spawn_child
|
23
|
+
r = fork
|
24
|
+
if r.nil?
|
25
|
+
work_it
|
26
|
+
else
|
27
|
+
r
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'gets every response from child processes' do
|
32
|
+
pid = nil
|
33
|
+
Redis.new(:db => 10).flushdb
|
34
|
+
begin
|
35
|
+
pids = (1..10).map{spawn_child}
|
36
|
+
responses = []
|
37
|
+
bus = MessageBus::ReliablePubSub.new(:db => 10)
|
38
|
+
Thread.new do
|
39
|
+
bus.subscribe("/response", 0) do |msg|
|
40
|
+
responses << msg if pids.include? msg.data.to_i
|
41
|
+
end
|
42
|
+
end
|
43
|
+
10.times{bus.publish("/echo", Process.pid.to_s)}
|
44
|
+
wait_for 4000 do
|
45
|
+
responses.count == 100
|
46
|
+
end
|
47
|
+
|
48
|
+
# p responses.group_by(&:data).map{|k,v|[k, v.count]}
|
49
|
+
# p responses.group_by(&:global_id).map{|k,v|[k, v.count]}
|
50
|
+
responses.count.should == 100
|
51
|
+
ensure
|
52
|
+
if pids
|
53
|
+
pids.each do |pid|
|
54
|
+
Process.kill("HUP", pid)
|
55
|
+
Process.wait(pid)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'message_bus'
|
3
|
+
|
4
|
+
describe MessageBus::ReliablePubSub do
|
5
|
+
|
6
|
+
def new_test_bus
|
7
|
+
MessageBus::ReliablePubSub.new(:db => 10)
|
8
|
+
end
|
9
|
+
|
10
|
+
before do
|
11
|
+
@bus = new_test_bus
|
12
|
+
@bus.reset!
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be able to access the backlog" do
|
16
|
+
@bus.publish "/foo", "bar"
|
17
|
+
@bus.publish "/foo", "baz"
|
18
|
+
|
19
|
+
@bus.backlog("/foo", 0).to_a.should == [
|
20
|
+
MessageBus::Message.new(1,1,'/foo','bar'),
|
21
|
+
MessageBus::Message.new(2,2,'/foo','baz')
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should truncate channels correctly" do
|
26
|
+
@bus.max_backlog_size = 2
|
27
|
+
4.times do |t|
|
28
|
+
@bus.publish "/foo", t.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
@bus.backlog("/foo").to_a.should == [
|
32
|
+
MessageBus::Message.new(3,3,'/foo','2'),
|
33
|
+
MessageBus::Message.new(4,4,'/foo','3'),
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should be able to grab a message by id" do
|
38
|
+
id1 = @bus.publish "/foo", "bar"
|
39
|
+
id2 = @bus.publish "/foo", "baz"
|
40
|
+
@bus.get_message("/foo", id2).should == MessageBus::Message.new(2, 2, "/foo", "baz")
|
41
|
+
@bus.get_message("/foo", id1).should == MessageBus::Message.new(1, 1, "/foo", "bar")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be able to access the global backlog" do
|
45
|
+
@bus.publish "/foo", "bar"
|
46
|
+
@bus.publish "/hello", "world"
|
47
|
+
@bus.publish "/foo", "baz"
|
48
|
+
@bus.publish "/hello", "planet"
|
49
|
+
|
50
|
+
@bus.global_backlog.to_a.should == [
|
51
|
+
MessageBus::Message.new(1, 1, "/foo", "bar"),
|
52
|
+
MessageBus::Message.new(2, 1, "/hello", "world"),
|
53
|
+
MessageBus::Message.new(3, 2, "/foo", "baz"),
|
54
|
+
MessageBus::Message.new(4, 2, "/hello", "planet")
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should correctly omit dropped messages from the global backlog" do
|
59
|
+
@bus.max_backlog_size = 1
|
60
|
+
@bus.publish "/foo", "a"
|
61
|
+
@bus.publish "/foo", "b"
|
62
|
+
@bus.publish "/bar", "a"
|
63
|
+
@bus.publish "/bar", "b"
|
64
|
+
|
65
|
+
@bus.global_backlog.to_a.should == [
|
66
|
+
MessageBus::Message.new(2, 2, "/foo", "b"),
|
67
|
+
MessageBus::Message.new(4, 2, "/bar", "b")
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should have the correct number of messages for multi threaded access" do
|
72
|
+
threads = []
|
73
|
+
4.times do
|
74
|
+
threads << Thread.new do
|
75
|
+
bus = new_test_bus
|
76
|
+
25.times {
|
77
|
+
bus.publish "/foo", "."
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
threads.each{|t| t.join}
|
83
|
+
@bus.backlog("/foo").length == 100
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be able to subscribe globally with recovery" do
|
87
|
+
@bus.publish("/foo", "1")
|
88
|
+
@bus.publish("/bar", "2")
|
89
|
+
got = []
|
90
|
+
|
91
|
+
t = Thread.new do
|
92
|
+
new_test_bus.global_subscribe(0) do |msg|
|
93
|
+
got << msg
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
@bus.publish("/bar", "3")
|
98
|
+
|
99
|
+
wait_for(100) do
|
100
|
+
got.length == 3
|
101
|
+
end
|
102
|
+
|
103
|
+
t.kill
|
104
|
+
|
105
|
+
got.length.should == 3
|
106
|
+
got.map{|m| m.data}.should == ["1","2","3"]
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should be able to encode and decode messages properly" do
|
110
|
+
m = MessageBus::Message.new 1,2,'||','||'
|
111
|
+
MessageBus::Message.decode(m.encode).should == m
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should handle subscribe on single channel, with recovery" do
|
115
|
+
@bus.publish("/foo", "1")
|
116
|
+
@bus.publish("/bar", "2")
|
117
|
+
got = []
|
118
|
+
|
119
|
+
t = Thread.new do
|
120
|
+
new_test_bus.subscribe("/foo",0) do |msg|
|
121
|
+
got << msg
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
@bus.publish("/foo", "3")
|
126
|
+
|
127
|
+
wait_for(100) do
|
128
|
+
got.length == 2
|
129
|
+
end
|
130
|
+
|
131
|
+
t.kill
|
132
|
+
|
133
|
+
got.map{|m| m.data}.should == ["1","3"]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should not get backlog if subscribe is called without params" do
|
137
|
+
@bus.publish("/foo", "1")
|
138
|
+
got = []
|
139
|
+
|
140
|
+
t = Thread.new do
|
141
|
+
new_test_bus.subscribe("/foo") do |msg|
|
142
|
+
got << msg
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# sleep 50ms to allow the bus to correctly subscribe,
|
147
|
+
# I thought about adding a subscribed callback, but outside of testing it matters less
|
148
|
+
sleep 0.05
|
149
|
+
|
150
|
+
@bus.publish("/foo", "2")
|
151
|
+
|
152
|
+
wait_for(100) do
|
153
|
+
got.length == 1
|
154
|
+
end
|
155
|
+
|
156
|
+
t.kill
|
157
|
+
|
158
|
+
got.map{|m| m.data}.should == ["2"]
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should allow us to get last id on a channel" do
|
162
|
+
@bus.last_id("/foo").should == 0
|
163
|
+
@bus.publish("/foo", "1")
|
164
|
+
@bus.last_id("/foo").should == 1
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|