message_bus 2.1.6 → 2.2.0.pre
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of message_bus might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop.yml +13 -92
- data/.rubocop_todo.yml +659 -0
- data/.travis.yml +1 -1
- data/CHANGELOG +61 -0
- data/Dockerfile +18 -0
- data/Gemfile +3 -1
- data/Guardfile +0 -1
- data/README.md +188 -101
- data/Rakefile +12 -1
- data/assets/message-bus.js +1 -1
- data/docker-compose.yml +46 -0
- data/examples/bench/config.ru +8 -9
- data/examples/bench/unicorn.conf.rb +1 -1
- data/examples/chat/chat.rb +150 -153
- data/examples/minimal/config.ru +2 -3
- data/lib/message_bus.rb +224 -36
- data/lib/message_bus/backends.rb +7 -0
- data/lib/message_bus/backends/base.rb +184 -0
- data/lib/message_bus/backends/memory.rb +304 -226
- data/lib/message_bus/backends/postgres.rb +359 -318
- data/lib/message_bus/backends/redis.rb +380 -337
- data/lib/message_bus/client.rb +99 -41
- data/lib/message_bus/connection_manager.rb +29 -21
- data/lib/message_bus/diagnostics.rb +50 -41
- data/lib/message_bus/distributed_cache.rb +5 -7
- data/lib/message_bus/message.rb +2 -2
- data/lib/message_bus/rack/diagnostics.rb +65 -55
- data/lib/message_bus/rack/middleware.rb +64 -44
- data/lib/message_bus/rack/thin_ext.rb +13 -9
- data/lib/message_bus/rails/railtie.rb +2 -0
- data/lib/message_bus/timer_thread.rb +2 -2
- data/lib/message_bus/version.rb +2 -1
- data/message_bus.gemspec +3 -2
- data/spec/assets/support/jasmine_helper.rb +1 -1
- data/spec/lib/fake_async_middleware.rb +1 -6
- data/spec/lib/message_bus/assets/asset_encoding_spec.rb +3 -3
- data/spec/lib/message_bus/backend_spec.rb +409 -0
- data/spec/lib/message_bus/client_spec.rb +8 -11
- data/spec/lib/message_bus/connection_manager_spec.rb +8 -14
- data/spec/lib/message_bus/distributed_cache_spec.rb +0 -4
- data/spec/lib/message_bus/multi_process_spec.rb +6 -7
- data/spec/lib/message_bus/rack/middleware_spec.rb +47 -43
- data/spec/lib/message_bus/timer_thread_spec.rb +0 -2
- data/spec/lib/message_bus_spec.rb +59 -43
- data/spec/spec_helper.rb +16 -4
- metadata +12 -9
- data/spec/lib/message_bus/backends/postgres_spec.rb +0 -221
- data/spec/lib/message_bus/backends/redis_spec.rb +0 -271
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative '../../../spec_helper'
|
2
2
|
asset_directory = File.expand_path('../../../../../assets', __FILE__)
|
3
3
|
asset_file_paths = Dir.glob(File.join(asset_directory, 'message-bus.js'))
|
4
|
-
asset_file_names = asset_file_paths.map{|e| File.basename(e) }
|
4
|
+
asset_file_names = asset_file_paths.map { |e| File.basename(e) }
|
5
5
|
|
6
6
|
describe asset_file_names do
|
7
7
|
it 'should contain .js files' do
|
@@ -9,10 +9,10 @@ describe asset_file_names do
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
asset_file_paths.each do |
|
12
|
+
asset_file_paths.each do |path|
|
13
13
|
describe "Asset file #{File.basename(path).inspect}" do
|
14
14
|
it 'should be encodable as UTF8' do
|
15
|
-
binary_data = File.open(path, 'rb'){|f| f.read }
|
15
|
+
binary_data = File.open(path, 'rb') { |f| f.read }
|
16
16
|
binary_data.encode(Encoding::UTF_8)
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,409 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require 'message_bus'
|
3
|
+
|
4
|
+
describe PUB_SUB_CLASS do
|
5
|
+
def new_test_bus
|
6
|
+
PUB_SUB_CLASS.new(MESSAGE_BUS_CONFIG)
|
7
|
+
end
|
8
|
+
|
9
|
+
before do
|
10
|
+
@bus = new_test_bus
|
11
|
+
@bus.reset!
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "API parity" do
|
15
|
+
it "has the same public methods as the base class" do
|
16
|
+
@bus.public_methods.sort.must_equal MessageBus::Backends::Base.new(MESSAGE_BUS_CONFIG).public_methods.sort
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be able to access the backlog" do
|
21
|
+
@bus.publish "/foo", "bar"
|
22
|
+
@bus.publish "/foo", "baz"
|
23
|
+
|
24
|
+
@bus.backlog("/foo", 0).to_a.must_equal [
|
25
|
+
MessageBus::Message.new(1, 1, '/foo', 'bar'),
|
26
|
+
MessageBus::Message.new(2, 2, '/foo', 'baz')
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should initialize with max_backlog_size" do
|
31
|
+
PUB_SUB_CLASS.new({}, 2000).max_backlog_size.must_equal 2000
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should truncate channels correctly" do
|
35
|
+
@bus.max_backlog_size = 2
|
36
|
+
[
|
37
|
+
"one",
|
38
|
+
"two",
|
39
|
+
"three",
|
40
|
+
"four",
|
41
|
+
].each do |t|
|
42
|
+
@bus.publish "/foo", t
|
43
|
+
end
|
44
|
+
|
45
|
+
@bus.backlog("/foo").to_a.must_equal [
|
46
|
+
MessageBus::Message.new(3, 3, '/foo', 'three'),
|
47
|
+
MessageBus::Message.new(4, 4, '/foo', 'four'),
|
48
|
+
]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should truncate global backlog correctly" do
|
52
|
+
@bus.max_global_backlog_size = 2
|
53
|
+
@bus.publish "/foo", "one"
|
54
|
+
@bus.publish "/bar", "two"
|
55
|
+
@bus.publish "/baz", "three"
|
56
|
+
|
57
|
+
@bus.global_backlog.length.must_equal 2
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be able to grab a message by id" do
|
61
|
+
id1 = @bus.publish "/foo", "bar"
|
62
|
+
id2 = @bus.publish "/foo", "baz"
|
63
|
+
@bus.get_message("/foo", id2).must_equal MessageBus::Message.new(2, 2, "/foo", "baz")
|
64
|
+
@bus.get_message("/foo", id1).must_equal MessageBus::Message.new(1, 1, "/foo", "bar")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have the correct number of messages for multi threaded access" do
|
68
|
+
threads = []
|
69
|
+
4.times do
|
70
|
+
threads << Thread.new do
|
71
|
+
25.times {
|
72
|
+
@bus.publish "/foo", "foo"
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
threads.each(&:join)
|
78
|
+
@bus.backlog("/foo").length == 100
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should be able to encode and decode messages properly" do
|
82
|
+
m = MessageBus::Message.new 1, 2, '||', '||'
|
83
|
+
MessageBus::Message.decode(m.encode).must_equal m
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should allow us to get last id on a channel" do
|
87
|
+
@bus.last_id("/foo").must_equal 0
|
88
|
+
@bus.publish("/foo", "one")
|
89
|
+
@bus.last_id("/foo").must_equal 1
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "readonly" do
|
93
|
+
after do
|
94
|
+
@bus.pub_redis.slaveof "no", "one"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should be able to store messages in memory for a period while in read only" do
|
98
|
+
test_only :redis
|
99
|
+
skip "This spec changes redis behavior that in turn means other specs run slow"
|
100
|
+
|
101
|
+
@bus.pub_redis.slaveof "127.0.0.80", "666"
|
102
|
+
@bus.max_in_memory_publish_backlog = 2
|
103
|
+
|
104
|
+
current_threads = Thread.list
|
105
|
+
current_threads_length = current_threads.count
|
106
|
+
|
107
|
+
3.times do
|
108
|
+
result = @bus.publish "/foo", "bar"
|
109
|
+
assert_nil result
|
110
|
+
Thread.list.length.must_equal(current_threads_length + 1)
|
111
|
+
end
|
112
|
+
|
113
|
+
@bus.pub_redis.slaveof "no", "one"
|
114
|
+
sleep 0.01
|
115
|
+
|
116
|
+
(Thread.list - current_threads).each(&:join)
|
117
|
+
Thread.list.length.must_equal current_threads_length
|
118
|
+
|
119
|
+
@bus.backlog("/foo", 0).map(&:data).must_equal ["bar", "bar"]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "can set backlog age" do
|
124
|
+
@bus.max_backlog_age = 1
|
125
|
+
|
126
|
+
expected_backlog_size = 0
|
127
|
+
|
128
|
+
# Start at time = 0s
|
129
|
+
@bus.publish "/foo", "bar"
|
130
|
+
expected_backlog_size += 1
|
131
|
+
|
132
|
+
@bus.global_backlog.length.must_equal expected_backlog_size
|
133
|
+
@bus.backlog("/foo", 0).length.must_equal expected_backlog_size
|
134
|
+
|
135
|
+
sleep 1.25 # Should now be at time =~ 1.25s. Our backlog should have expired by now.
|
136
|
+
expected_backlog_size = 0
|
137
|
+
|
138
|
+
case MESSAGE_BUS_CONFIG[:backend]
|
139
|
+
when :postgres
|
140
|
+
# Force triggering backlog expiry: postgres backend doesn't expire backlogs on a timer, but at publication time.
|
141
|
+
@bus.global_backlog.length.wont_equal expected_backlog_size
|
142
|
+
@bus.backlog("/foo", 0).length.wont_equal expected_backlog_size
|
143
|
+
@bus.publish "/foo", "baz"
|
144
|
+
expected_backlog_size += 1
|
145
|
+
end
|
146
|
+
|
147
|
+
# Assert that the backlog did expire, and now has only the new publication in it.
|
148
|
+
@bus.global_backlog.length.must_equal expected_backlog_size
|
149
|
+
@bus.backlog("/foo", 0).length.must_equal expected_backlog_size
|
150
|
+
|
151
|
+
sleep 0.75 # Should now be at time =~ 2s
|
152
|
+
|
153
|
+
@bus.publish "/foo", "baz" # Publish something else before another expiry
|
154
|
+
expected_backlog_size += 1
|
155
|
+
|
156
|
+
sleep 0.75 # Should now be at time =~ 2.75s
|
157
|
+
# Our oldest message is now 1.5s old, but we didn't cease publishing for a period of 1s at a time, so we should not have expired the backlog.
|
158
|
+
|
159
|
+
@bus.publish "/foo", "baz" # Publish something else to ward off another expiry
|
160
|
+
expected_backlog_size += 1
|
161
|
+
|
162
|
+
case MESSAGE_BUS_CONFIG[:backend]
|
163
|
+
when :postgres
|
164
|
+
# Postgres expires individual messages that have lived longer than the TTL, not whole backlogs
|
165
|
+
expected_backlog_size -= 1
|
166
|
+
else
|
167
|
+
# Assert that the backlog did not expire, and has all of our publications since the last expiry.
|
168
|
+
end
|
169
|
+
@bus.global_backlog.length.must_equal expected_backlog_size
|
170
|
+
@bus.backlog("/foo", 0).length.must_equal expected_backlog_size
|
171
|
+
end
|
172
|
+
|
173
|
+
it "can set backlog age on publish" do
|
174
|
+
@bus.max_backlog_age = 100
|
175
|
+
|
176
|
+
expected_backlog_size = 0
|
177
|
+
|
178
|
+
initial_id = @bus.last_id("/foo")
|
179
|
+
|
180
|
+
# Start at time = 0s
|
181
|
+
@bus.publish "/foo", "bar", max_backlog_age: 1
|
182
|
+
expected_backlog_size += 1
|
183
|
+
|
184
|
+
@bus.global_backlog.length.must_equal expected_backlog_size
|
185
|
+
@bus.backlog("/foo", 0).length.must_equal expected_backlog_size
|
186
|
+
|
187
|
+
sleep 1.25 # Should now be at time =~ 1.25s. Our backlog should have expired by now.
|
188
|
+
expected_backlog_size = 0
|
189
|
+
|
190
|
+
case MESSAGE_BUS_CONFIG[:backend]
|
191
|
+
when :postgres
|
192
|
+
# Force triggering backlog expiry: postgres backend doesn't expire backlogs on a timer, but at publication time.
|
193
|
+
@bus.global_backlog.length.wont_equal expected_backlog_size
|
194
|
+
@bus.backlog("/foo", 0).length.wont_equal expected_backlog_size
|
195
|
+
@bus.publish "/foo", "baz", max_backlog_age: 1
|
196
|
+
expected_backlog_size += 1
|
197
|
+
end
|
198
|
+
|
199
|
+
# Assert that the backlog did expire, and now has only the new publication in it.
|
200
|
+
@bus.global_backlog.length.must_equal expected_backlog_size
|
201
|
+
@bus.backlog("/foo", 0).length.must_equal expected_backlog_size
|
202
|
+
|
203
|
+
# for the time being we can give pg a pass here
|
204
|
+
# TODO: make the implementation here consistent
|
205
|
+
if MESSAGE_BUS_CONFIG[:backend] != :postgres
|
206
|
+
# ids are not opaque we expect them to be reset on our channel if it
|
207
|
+
# got cleared due to an expire, the reason for this is cause we will leak entries due to tracking
|
208
|
+
# this in turn can bloat storage for the backend
|
209
|
+
@bus.last_id("/foo").must_equal initial_id
|
210
|
+
end
|
211
|
+
|
212
|
+
sleep 0.75 # Should now be at time =~ 2s
|
213
|
+
|
214
|
+
@bus.publish "/foo", "baz", max_backlog_age: 1 # Publish something else before another expiry
|
215
|
+
expected_backlog_size += 1
|
216
|
+
|
217
|
+
sleep 0.75 # Should now be at time =~ 2.75s
|
218
|
+
# Our oldest message is now 1.5s old, but we didn't cease publishing for a period of 1s at a time, so we should not have expired the backlog.
|
219
|
+
|
220
|
+
@bus.publish "/foo", "baz", max_backlog_age: 1 # Publish something else to ward off another expiry
|
221
|
+
expected_backlog_size += 1
|
222
|
+
|
223
|
+
case MESSAGE_BUS_CONFIG[:backend]
|
224
|
+
when :postgres
|
225
|
+
# Postgres expires individual messages that have lived longer than the TTL, not whole backlogs
|
226
|
+
expected_backlog_size -= 1
|
227
|
+
else
|
228
|
+
# Assert that the backlog did not expire, and has all of our publications since the last expiry.
|
229
|
+
end
|
230
|
+
@bus.global_backlog.length.must_equal expected_backlog_size
|
231
|
+
@bus.backlog("/foo", 0).length.must_equal expected_backlog_size
|
232
|
+
end
|
233
|
+
|
234
|
+
it "can set backlog size on publish" do
|
235
|
+
@bus.max_backlog_size = 100
|
236
|
+
|
237
|
+
@bus.publish "/foo", "bar", max_backlog_size: 2
|
238
|
+
@bus.publish "/foo", "bar", max_backlog_size: 2
|
239
|
+
@bus.publish "/foo", "bar", max_backlog_size: 2
|
240
|
+
|
241
|
+
@bus.backlog("/foo").length.must_equal 2
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should be able to access the global backlog" do
|
245
|
+
@bus.publish "/foo", "bar"
|
246
|
+
@bus.publish "/hello", "world"
|
247
|
+
@bus.publish "/foo", "baz"
|
248
|
+
@bus.publish "/hello", "planet"
|
249
|
+
|
250
|
+
expected_messages = case MESSAGE_BUS_CONFIG[:backend]
|
251
|
+
when :redis
|
252
|
+
# Redis has channel-specific message IDs
|
253
|
+
[
|
254
|
+
MessageBus::Message.new(1, 1, "/foo", "bar"),
|
255
|
+
MessageBus::Message.new(2, 1, "/hello", "world"),
|
256
|
+
MessageBus::Message.new(3, 2, "/foo", "baz"),
|
257
|
+
MessageBus::Message.new(4, 2, "/hello", "planet")
|
258
|
+
]
|
259
|
+
else
|
260
|
+
[
|
261
|
+
MessageBus::Message.new(1, 1, "/foo", "bar"),
|
262
|
+
MessageBus::Message.new(2, 2, "/hello", "world"),
|
263
|
+
MessageBus::Message.new(3, 3, "/foo", "baz"),
|
264
|
+
MessageBus::Message.new(4, 4, "/hello", "planet")
|
265
|
+
]
|
266
|
+
end
|
267
|
+
|
268
|
+
@bus.global_backlog.to_a.must_equal expected_messages
|
269
|
+
end
|
270
|
+
|
271
|
+
it "should correctly omit dropped messages from the global backlog" do
|
272
|
+
@bus.max_backlog_size = 1
|
273
|
+
@bus.publish "/foo", "a1"
|
274
|
+
@bus.publish "/foo", "b1"
|
275
|
+
@bus.publish "/bar", "a1"
|
276
|
+
@bus.publish "/bar", "b1"
|
277
|
+
|
278
|
+
expected_messages = case MESSAGE_BUS_CONFIG[:backend]
|
279
|
+
when :redis
|
280
|
+
# Redis has channel-specific message IDs
|
281
|
+
[
|
282
|
+
MessageBus::Message.new(2, 2, "/foo", "b1"),
|
283
|
+
MessageBus::Message.new(4, 2, "/bar", "b1")
|
284
|
+
]
|
285
|
+
else
|
286
|
+
[
|
287
|
+
MessageBus::Message.new(2, 2, "/foo", "b1"),
|
288
|
+
MessageBus::Message.new(4, 4, "/bar", "b1")
|
289
|
+
]
|
290
|
+
end
|
291
|
+
|
292
|
+
@bus.global_backlog.to_a.must_equal expected_messages
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should cope with a storage reset cleanly" do
|
296
|
+
@bus.publish("/foo", "one")
|
297
|
+
got = []
|
298
|
+
|
299
|
+
t = Thread.new do
|
300
|
+
@bus.subscribe("/foo") do |msg|
|
301
|
+
got << msg
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
# sleep 50ms to allow the bus to correctly subscribe,
|
306
|
+
# I thought about adding a subscribed callback, but outside of testing it matters less
|
307
|
+
sleep 0.05
|
308
|
+
|
309
|
+
@bus.publish("/foo", "two")
|
310
|
+
|
311
|
+
@bus.reset!
|
312
|
+
|
313
|
+
@bus.publish("/foo", "three")
|
314
|
+
|
315
|
+
wait_for(100) do
|
316
|
+
got.length == 2
|
317
|
+
end
|
318
|
+
|
319
|
+
t.kill
|
320
|
+
|
321
|
+
got.map { |m| m.data }.must_equal ["two", "three"]
|
322
|
+
got[1].global_id.must_equal 1
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should support clear_every setting" do
|
326
|
+
test_never :redis
|
327
|
+
|
328
|
+
@bus.clear_every = 5
|
329
|
+
@bus.max_global_backlog_size = 2
|
330
|
+
@bus.publish "/foo", "11"
|
331
|
+
@bus.publish "/bar", "21"
|
332
|
+
@bus.publish "/baz", "31"
|
333
|
+
@bus.publish "/bar", "41"
|
334
|
+
@bus.global_backlog.length.must_equal 4
|
335
|
+
|
336
|
+
@bus.publish "/baz", "51"
|
337
|
+
@bus.global_backlog.length.must_equal 2
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should be able to subscribe globally with recovery" do
|
341
|
+
@bus.publish("/foo", "11")
|
342
|
+
@bus.publish("/bar", "12")
|
343
|
+
got = []
|
344
|
+
|
345
|
+
t = Thread.new do
|
346
|
+
@bus.global_subscribe(0) do |msg|
|
347
|
+
got << msg
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
@bus.publish("/bar", "13")
|
352
|
+
|
353
|
+
wait_for(100) do
|
354
|
+
got.length == 3
|
355
|
+
end
|
356
|
+
|
357
|
+
t.kill
|
358
|
+
|
359
|
+
got.length.must_equal 3
|
360
|
+
got.map { |m| m.data }.must_equal ["11", "12", "13"]
|
361
|
+
end
|
362
|
+
|
363
|
+
it "should handle subscribe on single channel, with recovery" do
|
364
|
+
@bus.publish("/foo", "11")
|
365
|
+
@bus.publish("/bar", "12")
|
366
|
+
got = []
|
367
|
+
|
368
|
+
t = Thread.new do
|
369
|
+
@bus.subscribe("/foo", 0) do |msg|
|
370
|
+
got << msg
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
@bus.publish("/foo", "13")
|
375
|
+
|
376
|
+
wait_for(100) do
|
377
|
+
got.length == 2
|
378
|
+
end
|
379
|
+
|
380
|
+
t.kill
|
381
|
+
|
382
|
+
got.map { |m| m.data }.must_equal ["11", "13"]
|
383
|
+
end
|
384
|
+
|
385
|
+
it "should not get backlog if subscribe is called without params" do
|
386
|
+
@bus.publish("/foo", "11")
|
387
|
+
got = []
|
388
|
+
|
389
|
+
t = Thread.new do
|
390
|
+
@bus.subscribe("/foo") do |msg|
|
391
|
+
got << msg
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
# sleep 50ms to allow the bus to correctly subscribe,
|
396
|
+
# I thought about adding a subscribed callback, but outside of testing it matters less
|
397
|
+
sleep 0.05
|
398
|
+
|
399
|
+
@bus.publish("/foo", "12")
|
400
|
+
|
401
|
+
wait_for(100) do
|
402
|
+
got.length == 1
|
403
|
+
end
|
404
|
+
|
405
|
+
t.kill
|
406
|
+
|
407
|
+
got.map { |m| m.data }.must_equal ["12"]
|
408
|
+
end
|
409
|
+
end
|
@@ -2,9 +2,7 @@ require_relative '../../spec_helper'
|
|
2
2
|
require 'message_bus'
|
3
3
|
|
4
4
|
describe MessageBus::Client do
|
5
|
-
|
6
5
|
describe "subscriptions" do
|
7
|
-
|
8
6
|
def setup_client(client_id)
|
9
7
|
MessageBus::Client.new client_id: client_id, message_bus: @bus
|
10
8
|
end
|
@@ -29,14 +27,15 @@ describe MessageBus::Client do
|
|
29
27
|
|
30
28
|
while line = lines.shift
|
31
29
|
break if line == ""
|
30
|
+
|
32
31
|
name, val = line.split(": ")
|
33
32
|
headers[name] = val
|
34
33
|
end
|
35
34
|
|
36
|
-
length = nil
|
37
35
|
while line = lines.shift
|
38
36
|
length = line.to_i(16)
|
39
37
|
break if length == 0
|
38
|
+
|
40
39
|
rest = lines.join("\r\n")
|
41
40
|
chunks << rest[0...length]
|
42
41
|
lines = (rest[length + 2..-1] || "").split("\r\n")
|
@@ -95,7 +94,6 @@ describe MessageBus::Client do
|
|
95
94
|
# end with []
|
96
95
|
chunk2 = parse_chunk(chunks[1])
|
97
96
|
chunk2.length.must_equal 0
|
98
|
-
|
99
97
|
end
|
100
98
|
|
101
99
|
it "does not bleed data accross sites" do
|
@@ -117,7 +115,6 @@ describe MessageBus::Client do
|
|
117
115
|
end
|
118
116
|
|
119
117
|
it "allows negative subscribes to look behind" do
|
120
|
-
|
121
118
|
@bus.publish '/hello', 'world'
|
122
119
|
@bus.publish '/hello', 'sam'
|
123
120
|
|
@@ -139,19 +136,21 @@ describe MessageBus::Client do
|
|
139
136
|
another_client = setup_client('def')
|
140
137
|
clients = [@client, another_client]
|
141
138
|
|
142
|
-
|
139
|
+
channel = SecureRandom.hex
|
140
|
+
|
141
|
+
clients.each { |client| client.subscribe(channel, nil) }
|
143
142
|
|
144
|
-
@bus.publish(
|
143
|
+
@bus.publish(channel, "world", client_ids: ['abc'])
|
145
144
|
|
146
145
|
log = @client.backlog
|
147
146
|
log.length.must_equal 1
|
148
|
-
log[0].channel.must_equal
|
147
|
+
log[0].channel.must_equal channel
|
149
148
|
log[0].data.must_equal 'world'
|
150
149
|
|
151
150
|
log = another_client.backlog
|
152
151
|
log.length.must_equal 1
|
153
152
|
log[0].channel.must_equal '/__status'
|
154
|
-
log[0].data.must_equal(
|
153
|
+
log[0].data.must_equal(channel => 1)
|
155
154
|
end
|
156
155
|
|
157
156
|
it "should provide a list of subscriptions" do
|
@@ -199,8 +198,6 @@ describe MessageBus::Client do
|
|
199
198
|
@client.group_ids = [77, 0, 10]
|
200
199
|
@client.allowed?(@message).must_equal true
|
201
200
|
end
|
202
|
-
|
203
201
|
end
|
204
202
|
end
|
205
|
-
|
206
203
|
end
|