beetle 3.3.12 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/RELEASE_NOTES.rdoc +19 -0
- data/beetle.gemspec +2 -2
- data/lib/beetle/base.rb +8 -6
- data/lib/beetle/client.rb +7 -0
- data/lib/beetle/deduplication_store.rb +1 -1
- 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 +6 -0
- data/test/beetle/deduplication_store_test.rb +1 -1
- data/test/beetle/message/settings_test.rb +4 -4
- data/test/beetle/message_test.rb +6 -14
- data/test/beetle/publisher_test.rb +42 -9
- data/test/beetle/subscriber_test.rb +11 -0
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb4bee36ae48b68aa27483c59aea588aa1a263c7c33858738ce6471246e1bb96
|
4
|
+
data.tar.gz: 93f380bb4596fcabfc48bec927ba7767b04b826750c307934ed937023c7a8152
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34d0e2001a1f93f8b88a86992a77bda65acddc1913c550798144c62fc11b77b7da0dcc0b0c270edd38aa7d27b7ea5f1d0f03fe2a955154db0f91759f5aaa2aee
|
7
|
+
data.tar.gz: 7ee1364e4fc0e6c6d8cefb1f10c5d4baa0fa6c7a1bd1434a710169538d104b4b83016faa3fb3bb6616bbae1c1db668953f24acd9c342d481b20b6e5d41c967de
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
+
== Version 3.5.0
|
4
|
+
* expose publisher method to setup queues/policies ahead of use
|
5
|
+
|
6
|
+
== Version 3.4.3
|
7
|
+
* optimize declaration of queues with many bindings
|
8
|
+
|
9
|
+
== Version 3.4.2
|
10
|
+
* Updated amq-protocol gem to version 2.3.2.
|
11
|
+
* Fixed a rare race condition on message handler timeouts.
|
12
|
+
|
13
|
+
== Version 3.4.1
|
14
|
+
* Updated amq-protocol gem to version 2.3.1.
|
15
|
+
|
16
|
+
== Version 3.4.0
|
17
|
+
* Require redis gem version 4.2.1. This version changes the exists to check for the
|
18
|
+
existence of multiple keys, return the number of keys in the list that exist. This
|
19
|
+
requires at least redis gem version 4.2.0, but 4.2.1 contains a bug fix for said
|
20
|
+
command.
|
21
|
+
|
3
22
|
== Version 3.3.12
|
4
23
|
* Support queue level declaration of dead letter queue message TTL.
|
5
24
|
|
data/beetle.gemspec
CHANGED
@@ -24,9 +24,9 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.specification_version = 3
|
26
26
|
s.add_runtime_dependency "bunny", "~> 0.7.12"
|
27
|
-
s.add_runtime_dependency "redis", ">=
|
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)
|
@@ -120,7 +120,7 @@ module Beetle
|
|
120
120
|
|
121
121
|
# check whether key with given suffix exists for a given <tt>msg_id</tt>.
|
122
122
|
def exists(msg_id, suffix)
|
123
|
-
with_failover { redis.exists(key(msg_id, suffix)) }
|
123
|
+
with_failover { redis.exists?(key(msg_id, suffix)) }
|
124
124
|
end
|
125
125
|
|
126
126
|
# flush the configured redis database. useful for testing.
|
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)
|
@@ -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
|
|
data/test/beetle/message_test.rb
CHANGED
@@ -141,9 +141,7 @@ module Beetle
|
|
141
141
|
|
142
142
|
message.process(@null_handler)
|
143
143
|
keys = @store.keys(message.msg_id)
|
144
|
-
|
145
|
-
assert !@store.redis.exists(key)
|
146
|
-
end
|
144
|
+
assert_equal 0, @store.redis.exists(*keys)
|
147
145
|
end
|
148
146
|
|
149
147
|
test "successful processing of a non redundant message should delete all keys from the database (except the status key, which should be set to expire)" do
|
@@ -159,11 +157,9 @@ module Beetle
|
|
159
157
|
message.process(@null_handler)
|
160
158
|
keys = @store.keys(message.msg_id)
|
161
159
|
status_key = keys.shift
|
162
|
-
assert @store.redis.exists(status_key)
|
160
|
+
assert @store.redis.exists?(status_key)
|
163
161
|
assert @store.redis.ttl(status_key) <= @config.redis_status_key_expiry_interval
|
164
|
-
|
165
|
-
assert !@store.redis.exists(key)
|
166
|
-
end
|
162
|
+
assert_equal 0, @store.redis.exists(*keys)
|
167
163
|
end
|
168
164
|
|
169
165
|
test "successful processing of a redundant message twice should delete all keys from the database" do
|
@@ -179,9 +175,7 @@ module Beetle
|
|
179
175
|
message.process(@null_handler)
|
180
176
|
|
181
177
|
keys = @store.keys(message.msg_id)
|
182
|
-
|
183
|
-
assert !@store.redis.exists(key)
|
184
|
-
end
|
178
|
+
assert_equal 0, @store.redis.exists(*keys)
|
185
179
|
end
|
186
180
|
|
187
181
|
test "successful processing of a redundant message twice should delete all keys from the database (except the status key, which should be set to expire)" do
|
@@ -199,11 +193,9 @@ module Beetle
|
|
199
193
|
|
200
194
|
keys = @store.keys(message.msg_id)
|
201
195
|
status_key = keys.shift
|
202
|
-
assert @store.redis.exists(status_key)
|
196
|
+
assert @store.redis.exists?(status_key)
|
203
197
|
assert @store.redis.ttl(status_key) <= @config.redis_status_key_expiry_interval
|
204
|
-
|
205
|
-
assert !@store.redis.exists(key)
|
206
|
-
end
|
198
|
+
assert_equal 0, @store.redis.exists(*keys)
|
207
199
|
end
|
208
200
|
|
209
201
|
test "successful processing of a redundant message once should insert all but the delay key and the exception count key into the database" do
|
@@ -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
|
@@ -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.0
|
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-01-22 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bunny
|
@@ -34,14 +34,14 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ">="
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 4.2.1
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
42
|
- - ">="
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
44
|
+
version: 4.2.1
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: hiredis
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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
|