beetle 3.4.0 → 3.5.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.
- checksums.yaml +4 -4
- data/RELEASE_NOTES.rdoc +17 -0
- data/beetle.gemspec +1 -1
- data/lib/beetle/base.rb +8 -6
- data/lib/beetle/client.rb +13 -2
- data/lib/beetle/message.rb +14 -12
- data/lib/beetle/publisher.rb +16 -10
- data/lib/beetle/subscriber.rb +7 -5
- data/lib/beetle/version.rb +1 -1
- data/script/analyze-expiries +25 -0
- data/script/analyze-redis-keys +15 -0
- data/script/expire-keys +14 -0
- data/test/beetle/client_test.rb +44 -3
- data/test/beetle/message/settings_test.rb +4 -4
- data/test/beetle/publisher_test.rb +42 -9
- data/test/beetle/subscriber_test.rb +12 -1
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dcaf90eaf1b11b7f6350bb34e17d73591616790ede7b43b6e98cef363dd3770
|
4
|
+
data.tar.gz: 55348c9ce61cc2f43869f9c12cd26bbc5dc033b0e0a0506c0a821d6a6e24862c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6daabfea72ab76b0fa6944d35cee52139678f9a02a272e86a32af6045750496ee81b96ff685eee1bbe9617030b981df3718b7569efabc98df59f894127da29d1
|
7
|
+
data.tar.gz: 04d599595b4c39e62a78b496b284a67bed1a545e759d9a094facc757e0334ed16e4bdd7bab4f7bfabb7b6f63da0e590351e86d0da55328ab6db898e9ceaaef7f
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
+
== Version 3.5.1
|
4
|
+
* remove blank entries from server list strings
|
5
|
+
* make sure not to subscribe to any server twice
|
6
|
+
|
7
|
+
== Version 3.5.0
|
8
|
+
* expose publisher method to setup queues/policies ahead of use
|
9
|
+
|
10
|
+
== Version 3.4.3
|
11
|
+
* optimize declaration of queues with many bindings
|
12
|
+
|
13
|
+
== Version 3.4.2
|
14
|
+
* Updated amq-protocol gem to version 2.3.2.
|
15
|
+
* Fixed a rare race condition on message handler timeouts.
|
16
|
+
|
17
|
+
== Version 3.4.1
|
18
|
+
* Updated amq-protocol gem to version 2.3.1.
|
19
|
+
|
3
20
|
== Version 3.4.0
|
4
21
|
* Require redis gem version 4.2.1. This version changes the exists to check for the
|
5
22
|
existence of multiple keys, return the number of keys in the list that exist. This
|
data/beetle.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.add_runtime_dependency "bunny", "~> 0.7.12"
|
27
27
|
s.add_runtime_dependency "redis", ">= 4.2.1"
|
28
28
|
s.add_runtime_dependency "hiredis", ">= 0.4.5"
|
29
|
-
s.add_runtime_dependency "amq-protocol", "= 2.3.
|
29
|
+
s.add_runtime_dependency "amq-protocol", "= 2.3.2"
|
30
30
|
s.add_runtime_dependency "amqp", "= 1.8.0"
|
31
31
|
s.add_runtime_dependency "activesupport", ">= 2.3.4"
|
32
32
|
|
data/lib/beetle/base.rb
CHANGED
@@ -67,23 +67,25 @@ module Beetle
|
|
67
67
|
logger.debug("Beetle: binding queue #{name} with internal name #{opts[:amqp_name]} on server #{@server}")
|
68
68
|
queue_name = opts[:amqp_name]
|
69
69
|
creation_options = opts.slice(*QUEUE_CREATION_KEYS)
|
70
|
-
|
70
|
+
|
71
|
+
the_queue = declare_queue!(queue_name, creation_options)
|
71
72
|
@client.bindings[name].each do |binding_options|
|
72
73
|
exchange_name = binding_options[:exchange]
|
73
74
|
binding_options = binding_options.slice(*QUEUE_BINDING_KEYS)
|
74
|
-
|
75
|
+
logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_options.inspect}")
|
76
|
+
bind_queue!(the_queue, exchange_name, binding_options)
|
75
77
|
end
|
76
78
|
the_queue
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
80
|
-
def bind_dead_letter_queue!(channel, target_queue,
|
82
|
+
def bind_dead_letter_queue!(channel, target_queue, creation_options = {})
|
81
83
|
policy_options = @client.queues[target_queue].slice(:dead_lettering, :lazy, :dead_lettering_msg_ttl)
|
82
84
|
policy_options[:message_ttl] = policy_options.delete(:dead_lettering_msg_ttl)
|
83
85
|
dead_letter_queue_name = "#{target_queue}_dead_letter"
|
84
86
|
if policy_options[:dead_lettering]
|
85
|
-
logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{
|
86
|
-
channel.queue(dead_letter_queue_name,
|
87
|
+
logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_options.inspect}")
|
88
|
+
channel.queue(dead_letter_queue_name, creation_options)
|
87
89
|
end
|
88
90
|
return {
|
89
91
|
:queue_name => target_queue,
|
@@ -93,7 +95,7 @@ module Beetle
|
|
93
95
|
}.merge(policy_options)
|
94
96
|
end
|
95
97
|
|
96
|
-
# called by <tt>
|
98
|
+
# called by <tt>declare_queue!</tt>
|
97
99
|
def publish_policy_options(options)
|
98
100
|
# avoid endless recursion
|
99
101
|
return if options[:queue_name] == @client.config.beetle_policy_updates_queue_name
|
data/lib/beetle/client.rb
CHANGED
@@ -280,6 +280,13 @@ module Beetle
|
|
280
280
|
publisher.throttled?
|
281
281
|
end
|
282
282
|
|
283
|
+
# set up queues and policies for all configured queues. Otherwise this will
|
284
|
+
# happen on first use of an exchange, which can be undesired for latency
|
285
|
+
# sensitive endpoints. Only needs to be called once.
|
286
|
+
def setup_queues_and_policies
|
287
|
+
publisher.setup_queues_and_policies
|
288
|
+
end
|
289
|
+
|
283
290
|
# traces queues without consuming them. useful for debugging message flow.
|
284
291
|
def trace(queue_names=self.queues.keys, tracer=nil, &block)
|
285
292
|
queues_to_trace = self.queues.slice(*queue_names)
|
@@ -378,8 +385,12 @@ module Beetle
|
|
378
385
|
end
|
379
386
|
|
380
387
|
def load_brokers_from_config
|
381
|
-
@servers = config.servers
|
382
|
-
@additional_subscription_servers = config.additional_subscription_servers
|
388
|
+
@servers = parse_server_list(config.servers)
|
389
|
+
@additional_subscription_servers = parse_server_list(config.additional_subscription_servers) - @servers
|
390
|
+
end
|
391
|
+
|
392
|
+
def parse_server_list(s)
|
393
|
+
s.split(/ *, */).uniq.reject(&:blank?)
|
383
394
|
end
|
384
395
|
end
|
385
396
|
end
|
data/lib/beetle/message.rb
CHANGED
@@ -18,6 +18,8 @@ module Beetle
|
|
18
18
|
# forcefully abort a running handler after this many seconds.
|
19
19
|
# can be overriden when registering a handler.
|
20
20
|
DEFAULT_HANDLER_TIMEOUT = 600.seconds
|
21
|
+
# How much extra time on top of the handler timeout we add before considering a handler timed out
|
22
|
+
TIMEOUT_GRACE_PERIOD = 10.seconds
|
21
23
|
# how many times we should try to run a handler before giving up
|
22
24
|
DEFAULT_HANDLER_EXECUTION_ATTEMPTS = 1
|
23
25
|
# how many seconds we should wait before retrying handler execution
|
@@ -167,8 +169,8 @@ module Beetle
|
|
167
169
|
end
|
168
170
|
|
169
171
|
# handler timed out?
|
170
|
-
def timed_out?
|
171
|
-
(t
|
172
|
+
def timed_out?(t = nil)
|
173
|
+
(t ||= @store.get(msg_id, :timeout)) && (t.to_i + TIMEOUT_GRACE_PERIOD) < now
|
172
174
|
end
|
173
175
|
|
174
176
|
# reset handler timeout in the deduplication store
|
@@ -187,8 +189,8 @@ module Beetle
|
|
187
189
|
end
|
188
190
|
|
189
191
|
# whether we should wait before running the handler
|
190
|
-
def delayed?
|
191
|
-
(t
|
192
|
+
def delayed?(t = nil)
|
193
|
+
(t ||= @store.get(msg_id, :delay)) && t.to_i > now
|
192
194
|
end
|
193
195
|
|
194
196
|
# store delay value in the deduplication store
|
@@ -207,8 +209,8 @@ module Beetle
|
|
207
209
|
end
|
208
210
|
|
209
211
|
# whether we have already tried running the handler as often as specified when the handler was registered
|
210
|
-
def attempts_limit_reached?
|
211
|
-
(
|
212
|
+
def attempts_limit_reached?(attempts = nil)
|
213
|
+
(attempts ||= @store.get(msg_id, :attempts)) && attempts.to_i >= attempts_limit
|
212
214
|
end
|
213
215
|
|
214
216
|
# increment number of exception occurences in the deduplication store
|
@@ -217,8 +219,8 @@ module Beetle
|
|
217
219
|
end
|
218
220
|
|
219
221
|
# whether the number of exceptions has exceeded the limit set when the handler was registered
|
220
|
-
def exceptions_limit_reached?
|
221
|
-
@store.get(msg_id, :exceptions).to_i > exceptions_limit
|
222
|
+
def exceptions_limit_reached?(exceptions = nil)
|
223
|
+
(exceptions ||= @store.get(msg_id, :exceptions)) && exceptions.to_i > exceptions_limit
|
222
224
|
end
|
223
225
|
|
224
226
|
def exception_accepted?
|
@@ -306,17 +308,17 @@ module Beetle
|
|
306
308
|
if status == "completed"
|
307
309
|
ack!
|
308
310
|
RC::OK
|
309
|
-
elsif delay && delay
|
311
|
+
elsif delay && delayed?(delay)
|
310
312
|
logger.warn "Beetle: ignored delayed message (#{msg_id})!"
|
311
313
|
RC::Delayed
|
312
|
-
elsif !(timeout && timeout
|
314
|
+
elsif !(timeout && timed_out?(timeout))
|
313
315
|
RC::HandlerNotYetTimedOut
|
314
|
-
elsif attempts
|
316
|
+
elsif attempts && attempts_limit_reached?(attempts)
|
315
317
|
completed!
|
316
318
|
ack!
|
317
319
|
logger.warn "Beetle: reached the handler execution attempts limit: #{attempts_limit} on #{msg_id}"
|
318
320
|
RC::AttemptsLimitReached
|
319
|
-
elsif exceptions
|
321
|
+
elsif exceptions && exceptions_limit_reached?(exceptions)
|
320
322
|
completed!
|
321
323
|
ack!
|
322
324
|
logger.warn "Beetle: reached the handler exceptions limit: #{exceptions_limit} on #{msg_id}"
|
data/lib/beetle/publisher.rb
CHANGED
@@ -169,10 +169,14 @@ module Beetle
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
def setup_queues_and_policies
|
172
|
+
def setup_queues_and_policies
|
173
173
|
each_server do
|
174
|
-
|
175
|
-
|
174
|
+
begin
|
175
|
+
@client.queues.keys.each do |name|
|
176
|
+
queue(name)
|
177
|
+
end
|
178
|
+
rescue => e
|
179
|
+
logger.warn "Beetle: failed setting up queues and policies on #{@server}: #{e}"
|
176
180
|
end
|
177
181
|
end
|
178
182
|
end
|
@@ -247,17 +251,19 @@ module Beetle
|
|
247
251
|
@exchanges_with_bound_queues[exchange_name] = true
|
248
252
|
end
|
249
253
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
queue.bind(exchange(exchange_name), binding_keys)
|
256
|
-
policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_keys)
|
254
|
+
def declare_queue!(queue_name, creation_options)
|
255
|
+
logger.debug("Beetle: creating queue with opts: #{creation_options.inspect}")
|
256
|
+
queue = bunny.queue(queue_name, creation_options)
|
257
|
+
|
258
|
+
policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_options)
|
257
259
|
publish_policy_options(policy_options)
|
258
260
|
queue
|
259
261
|
end
|
260
262
|
|
263
|
+
def bind_queue!(queue, exchange_name, binding_options)
|
264
|
+
queue.bind(exchange(exchange_name), binding_options)
|
265
|
+
end
|
266
|
+
|
261
267
|
def stop!(exception=nil)
|
262
268
|
return unless bunny?
|
263
269
|
timeout = @client.config.publishing_timeout + @client.config.publisher_connect_timeout + 1
|
data/lib/beetle/subscriber.rb
CHANGED
@@ -214,18 +214,20 @@ module Beetle
|
|
214
214
|
channel.__send__(opts[:type], name, opts.slice(*EXCHANGE_CREATION_KEYS))
|
215
215
|
end
|
216
216
|
|
217
|
-
def
|
218
|
-
queue = channel.queue(queue_name,
|
217
|
+
def declare_queue!(queue_name, creation_options)
|
218
|
+
queue = channel.queue(queue_name, creation_options)
|
219
219
|
unless tracing?
|
220
220
|
# we don't want to create dead-letter queues for tracing
|
221
|
-
policy_options = bind_dead_letter_queue!(channel, queue_name,
|
221
|
+
policy_options = bind_dead_letter_queue!(channel, queue_name, creation_options)
|
222
222
|
publish_policy_options(policy_options)
|
223
223
|
end
|
224
|
-
exchange = exchange(exchange_name)
|
225
|
-
queue.bind(exchange, binding_keys)
|
226
224
|
queue
|
227
225
|
end
|
228
226
|
|
227
|
+
def bind_queue!(queue, exchange_name, binding_options)
|
228
|
+
queue.bind(exchange(exchange_name), binding_options)
|
229
|
+
end
|
230
|
+
|
229
231
|
def connection_settings
|
230
232
|
{
|
231
233
|
:host => current_host, :port => current_port, :logging => false,
|
data/lib/beetle/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
counts = Hash.new(0)
|
6
|
+
expiries = Hash.new{|h,k| h[k] = Hash.new(0)}
|
7
|
+
t = Time.now.to_i
|
8
|
+
|
9
|
+
File.open(ARGV[0]).each_line do |l|
|
10
|
+
parts = l.split(':')
|
11
|
+
queue = parts[1]
|
12
|
+
counts[queue] += 1
|
13
|
+
expiry = parts[4].to_i
|
14
|
+
expires_in = ((expiry - t)/(3600.0)).ceil
|
15
|
+
expiries[queue][expires_in] += 1
|
16
|
+
end
|
17
|
+
|
18
|
+
counts.to_a.sort_by{|_,v| -v}.each do |q,v|
|
19
|
+
puts "------------------------------------------------------------------"
|
20
|
+
puts "#{q}: #{v}"
|
21
|
+
puts "------------------------------------------------------------------"
|
22
|
+
expiries[q].to_a.sort_by{|k,_| -k}.each do |expiry, count|
|
23
|
+
printf "%3dh: %6d\n", expiry, count
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
queue_counts = Hash.new { |h,k| h[k] = 0 }
|
3
|
+
File.open(ARGV[0]).each_line do |l|
|
4
|
+
next if l == "lastgc" || l == "clients-last-seen"
|
5
|
+
a = l.split(':')
|
6
|
+
if a[0] == "msgid"
|
7
|
+
queue_counts[a[1]] += 1
|
8
|
+
else
|
9
|
+
queue_counts["none"] += 1
|
10
|
+
end
|
11
|
+
end
|
12
|
+
sorted_queues = queue_counts.to_a.sort_by{|a| -a[1]}
|
13
|
+
sorted_queues.each do |q,c|
|
14
|
+
puts "#{c}:#{q}"
|
15
|
+
end
|
data/script/expire-keys
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "redis"
|
3
|
+
|
4
|
+
redis = Redis.new(:host => "beetle-1.redis.ams2.xing.com", :port => 6379, :db => 0)
|
5
|
+
|
6
|
+
File.open(ARGV[0]).each_line.each_slice(10) do |s|
|
7
|
+
redis.pipelined do
|
8
|
+
s.each do |l|
|
9
|
+
l.chomp!
|
10
|
+
next if l =~ /^beetle:.*$/
|
11
|
+
redis.expire(l, 600)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/test/beetle/client_test.rb
CHANGED
@@ -282,6 +282,12 @@ module Beetle
|
|
282
282
|
client.stop_publishing
|
283
283
|
end
|
284
284
|
|
285
|
+
test "should delegate setup_queues_and_policies to the publisher instance" do
|
286
|
+
client = Client.new
|
287
|
+
client.send(:publisher).expects(:setup_queues_and_policies)
|
288
|
+
client.setup_queues_and_policies
|
289
|
+
end
|
290
|
+
|
285
291
|
test "should delegate queue purging to the publisher instance" do
|
286
292
|
client = Client.new
|
287
293
|
client.register_queue(:queue)
|
@@ -337,17 +343,17 @@ module Beetle
|
|
337
343
|
|
338
344
|
test "trying to listen to an unknown queue should raise an exception" do
|
339
345
|
client = Client.new
|
340
|
-
assert_raises(UnknownQueue) {
|
346
|
+
assert_raises(UnknownQueue) { client.listen_queues([:foobar])}
|
341
347
|
end
|
342
348
|
|
343
349
|
test "trying to pause listening on an unknown queue should raise an exception" do
|
344
350
|
client = Client.new
|
345
|
-
assert_raises(UnknownQueue) {
|
351
|
+
assert_raises(UnknownQueue) { client.pause_listening(:foobar)}
|
346
352
|
end
|
347
353
|
|
348
354
|
test "trying to resume listening on an unknown queue should raise an exception" do
|
349
355
|
client = Client.new
|
350
|
-
assert_raises(UnknownQueue) {
|
356
|
+
assert_raises(UnknownQueue) { client.pause_listening(:foobar)}
|
351
357
|
end
|
352
358
|
|
353
359
|
test "should delegate stop_listening to the subscriber instance" do
|
@@ -451,4 +457,39 @@ module Beetle
|
|
451
457
|
msg_stub
|
452
458
|
end
|
453
459
|
end
|
460
|
+
|
461
|
+
class ServerDeduplicationTest < Minitest::Test
|
462
|
+
def setup
|
463
|
+
@config = Configuration.new
|
464
|
+
@config.servers = "localhost:5672,localhost:5672"
|
465
|
+
@config.additional_subscription_servers = @config.servers + ",localhost:1234,localhost:1234"
|
466
|
+
@client = Client.new(@config)
|
467
|
+
end
|
468
|
+
|
469
|
+
test "duplicates are removed from the server list" do
|
470
|
+
assert_equal ["localhost:5672"], @client.servers
|
471
|
+
end
|
472
|
+
|
473
|
+
test "duplicates and servers in the server list are removed from the additional subscription server list" do
|
474
|
+
assert_equal ["localhost:1234"], @client.additional_subscription_servers
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
class EmptyServerStringTest < Minitest::Test
|
479
|
+
def setup
|
480
|
+
@config = Configuration.new
|
481
|
+
@config.servers = "localhost:5672,\t,localhost:5672, "
|
482
|
+
@config.additional_subscription_servers = @config.servers + ",localhost:1234, , ,,"
|
483
|
+
@client = Client.new(@config)
|
484
|
+
end
|
485
|
+
|
486
|
+
test "empty strings are removed from the server list" do
|
487
|
+
assert_equal ["localhost:5672"], @client.servers
|
488
|
+
end
|
489
|
+
|
490
|
+
test "empty strings are removed from the additional subscription server list" do
|
491
|
+
assert_equal ["localhost:1234"], @client.additional_subscription_servers
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
454
495
|
end
|
@@ -75,9 +75,9 @@ module Beetle
|
|
75
75
|
message.expects(:now).returns(1)
|
76
76
|
message.set_timeout!
|
77
77
|
assert_equal "2", @store.get(message.msg_id, :timeout)
|
78
|
-
message.expects(:now).returns(2)
|
78
|
+
message.expects(:now).returns(2 + Message::TIMEOUT_GRACE_PERIOD)
|
79
79
|
assert !message.timed_out?
|
80
|
-
message.expects(:now).returns(3)
|
80
|
+
message.expects(:now).returns(3 + Message::TIMEOUT_GRACE_PERIOD)
|
81
81
|
assert message.timed_out?
|
82
82
|
end
|
83
83
|
|
@@ -86,9 +86,9 @@ module Beetle
|
|
86
86
|
message.expects(:now).returns(0)
|
87
87
|
message.set_timeout!
|
88
88
|
assert_equal "#{Message::DEFAULT_HANDLER_TIMEOUT}", @store.get(message.msg_id, :timeout)
|
89
|
-
message.expects(:now).returns(message.timeout)
|
89
|
+
message.expects(:now).returns(message.timeout + Message::TIMEOUT_GRACE_PERIOD)
|
90
90
|
assert !message.timed_out?
|
91
|
-
message.expects(:now).returns(Message::
|
91
|
+
message.expects(:now).returns(message.timeout + Message::TIMEOUT_GRACE_PERIOD + 1)
|
92
92
|
assert message.timed_out?
|
93
93
|
end
|
94
94
|
|
@@ -304,7 +304,9 @@ module Beetle
|
|
304
304
|
@client.register_queue('test_queue_1', :exchange => 'test_exchange')
|
305
305
|
@client.register_queue('test_queue_2', :exchange => 'test_exchange')
|
306
306
|
@client.register_queue('test_queue_3', :exchange => 'test_exchange_2')
|
307
|
-
|
307
|
+
queue = mock("queue")
|
308
|
+
queue.expects(:bind).times(3)
|
309
|
+
@pub.expects(:declare_queue!).returns(queue).times(3)
|
308
310
|
@pub.send(:bind_queues_for_exchange, 'test_exchange')
|
309
311
|
@pub.send(:bind_queues_for_exchange, 'test_exchange_2')
|
310
312
|
end
|
@@ -312,8 +314,19 @@ module Beetle
|
|
312
314
|
test "should not rebind the defined queues for the used exchanges if they already have been bound" do
|
313
315
|
@client.register_queue('test_queue_1', :exchange => 'test_exchange')
|
314
316
|
@client.register_queue('test_queue_2', :exchange => 'test_exchange')
|
315
|
-
|
317
|
+
queue = mock("queue")
|
318
|
+
queue.expects(:bind).twice
|
319
|
+
@pub.expects(:declare_queue!).returns(queue).twice
|
320
|
+
@pub.send(:bind_queues_for_exchange, 'test_exchange')
|
316
321
|
@pub.send(:bind_queues_for_exchange, 'test_exchange')
|
322
|
+
end
|
323
|
+
|
324
|
+
test "should declare queues only once even with many bindings" do
|
325
|
+
@client.register_queue('test_queue', :exchange => 'test_exchange')
|
326
|
+
@client.register_binding('test_queue', :exchange => 'test_exchange', :key => 'sir-message-a-lot')
|
327
|
+
queue = mock("queue")
|
328
|
+
queue.expects(:bind).twice
|
329
|
+
@pub.expects(:declare_queue!).returns(queue).once
|
317
330
|
@pub.send(:bind_queues_for_exchange, 'test_exchange')
|
318
331
|
end
|
319
332
|
|
@@ -342,14 +355,34 @@ module Beetle
|
|
342
355
|
end
|
343
356
|
|
344
357
|
test "setting up queues and policies should iterate over all servers" do
|
345
|
-
|
346
|
-
|
358
|
+
client = Client.new
|
359
|
+
client.register_queue("queue")
|
360
|
+
pub = Publisher.new(client)
|
361
|
+
pub.servers = %w(a b)
|
362
|
+
|
347
363
|
s = sequence("setup")
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
364
|
+
pub.expects(:set_current_server).with("a").in_sequence(s)
|
365
|
+
pub.expects(:queue).with(client.config.beetle_policy_updates_queue_name).in_sequence(s)
|
366
|
+
pub.expects(:queue).with("queue").in_sequence(s)
|
367
|
+
pub.expects(:set_current_server).with("b").in_sequence(s)
|
368
|
+
pub.expects(:queue).with(client.config.beetle_policy_updates_queue_name).in_sequence(s)
|
369
|
+
pub.expects(:queue).with("queue").in_sequence(s)
|
370
|
+
|
371
|
+
pub.setup_queues_and_policies()
|
372
|
+
end
|
373
|
+
|
374
|
+
test "setting up queues and policies should handle ephemeral errors" do
|
375
|
+
client = Client.new
|
376
|
+
pub = Publisher.new(client)
|
377
|
+
client.register_queue("queue")
|
378
|
+
pub.servers = %w(a b)
|
379
|
+
pub.stubs(:queue).raises(StandardError)
|
380
|
+
|
381
|
+
s = sequence("setup")
|
382
|
+
pub.expects(:set_current_server).with("a").in_sequence(s)
|
383
|
+
pub.expects(:set_current_server).with("b").in_sequence(s)
|
384
|
+
|
385
|
+
pub.setup_queues_and_policies()
|
353
386
|
end
|
354
387
|
|
355
388
|
test "reports whether it has been throttled" do
|
@@ -127,7 +127,7 @@ module Beetle
|
|
127
127
|
@sub = @client.send(:subscriber)
|
128
128
|
end
|
129
129
|
|
130
|
-
test "subscribers server list should contain
|
130
|
+
test "subscribers server list should contain additional subcription hosts" do
|
131
131
|
assert_equal ["localhost:5672", "localhost:1234"], @sub.servers
|
132
132
|
end
|
133
133
|
end
|
@@ -168,6 +168,17 @@ module Beetle
|
|
168
168
|
@sub.send(:bind_queues, %W(x y))
|
169
169
|
end
|
170
170
|
|
171
|
+
test "binding queues with many bindings should create it only once" do
|
172
|
+
@client.register_queue(:x, :exchange => 'test_exchange')
|
173
|
+
@client.register_binding(:x, :exchange => 'test_exchange', :key => 'sir-message-a-lot')
|
174
|
+
@client.register_handler(%w(x)){}
|
175
|
+
@sub.stubs(:exchange)
|
176
|
+
queue = mock("queue")
|
177
|
+
queue.expects(:bind).twice
|
178
|
+
@sub.expects(:declare_queue!).returns(queue).once
|
179
|
+
@sub.send(:bind_queues, %W(x))
|
180
|
+
end
|
181
|
+
|
171
182
|
test "subscribing to queues should subscribe on all queues" do
|
172
183
|
@client.register_queue(:x)
|
173
184
|
@client.register_queue(:y)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beetle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kaes
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2021-06-01 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bunny
|
@@ -62,14 +62,14 @@ dependencies:
|
|
62
62
|
requirements:
|
63
63
|
- - '='
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: 2.3.
|
65
|
+
version: 2.3.2
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
68
|
version_requirements: !ruby/object:Gem::Requirement
|
69
69
|
requirements:
|
70
70
|
- - '='
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version: 2.3.
|
72
|
+
version: 2.3.2
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
74
|
name: amqp
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -337,7 +337,10 @@ files:
|
|
337
337
|
- lib/beetle/redis_ext.rb
|
338
338
|
- lib/beetle/subscriber.rb
|
339
339
|
- lib/beetle/version.rb
|
340
|
+
- script/analyze-expiries
|
341
|
+
- script/analyze-redis-keys
|
340
342
|
- script/console
|
343
|
+
- script/expire-keys
|
341
344
|
- script/start_rabbit
|
342
345
|
- test/beetle/amqp_gem_behavior_test.rb
|
343
346
|
- test/beetle/base_test.rb
|
@@ -375,7 +378,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
375
378
|
- !ruby/object:Gem::Version
|
376
379
|
version: 1.3.7
|
377
380
|
requirements: []
|
378
|
-
rubygems_version: 3.
|
381
|
+
rubygems_version: 3.2.16
|
379
382
|
signing_key:
|
380
383
|
specification_version: 3
|
381
384
|
summary: High Availability AMQP Messaging with Redundant Queues
|