beetle 2.3.2 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +6 -3
- data/RELEASE_NOTES.rdoc +8 -0
- data/Rakefile +7 -0
- data/features/redis_auto_failover.feature +1 -0
- data/features/step_definitions/redis_auto_failover_steps.rb +7 -0
- data/features/support/test_daemons/redis_configuration_server.rb +1 -1
- data/lib/beetle/base.rb +11 -4
- data/lib/beetle/client.rb +13 -1
- data/lib/beetle/dead_lettering.rb +23 -18
- data/lib/beetle/deduplication_store.rb +1 -1
- data/lib/beetle/publisher.rb +12 -2
- data/lib/beetle/subscriber.rb +9 -7
- data/lib/beetle/version.rb +1 -1
- data/test/beetle/client_test.rb +8 -1
- data/test/beetle/dead_lettering_test.rb +17 -15
- data/test/beetle/publisher_test.rb +47 -1
- data/test/beetle/subscriber_test.rb +20 -7
- metadata +2 -3
- data/examples/murks.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 299657b394d85d53b70417554db9a3ca53de5339dc0fc777e1555536237ccf1b
|
4
|
+
data.tar.gz: a4fda19185d645fbb26e563b7b7c72ffe67d03ef3cc621a581b7b1cee38b3178
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b6c98dd094e445db0424aab1c992eb9245df6fb4e402c45d087c8ca395c9bfd2f3ec57d95999a79ce5f4853d1c02e139a829b962f6cef896c73004a299743ad
|
7
|
+
data.tar.gz: 1324bd1753c97574cf0dd657f7096be41e26d76f271525c124aa198286056cbd8673bf5ff0894bc761b94351cdd14d1dbd3504e3925fcc6e11804f6ae99b19dd
|
data/README.rdoc
CHANGED
@@ -96,6 +96,7 @@ For development, you'll need
|
|
96
96
|
* {mocha}[http://github.com/floehopper/mocha]
|
97
97
|
* {cucumber}[http://github.com/aslakhellesoy/cucumber]
|
98
98
|
* {daemon_controller}[http://github.com/FooBarWidget/daemon_controller]
|
99
|
+
* {consul}[https://www.consul.io/downloads.html]
|
99
100
|
|
100
101
|
For tests, you'll need
|
101
102
|
* {activerecord}[https://github.com/rails/rails/tree/master/activerecord]
|
@@ -120,9 +121,11 @@ distribution.
|
|
120
121
|
|
121
122
|
1. Fork it
|
122
123
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
123
|
-
3.
|
124
|
-
|
125
|
-
|
124
|
+
3. Hack along and test your code using rake test and rake
|
125
|
+
cucumber. You must start consul in order to use cucumber.
|
126
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
127
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
128
|
+
6. Create new Pull Request
|
126
129
|
|
127
130
|
Don't increase the gem version in your pull requests. It will be done after merging the request,
|
128
131
|
to allow merging of pull requests in a flexible order.
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
+
|
4
|
+
== Version 3.0.0.rc1
|
5
|
+
* provide client method to setup queues and queue policies.
|
6
|
+
Setting up queue policies on demand in publisher and subscriber is OK
|
7
|
+
for a small number of queues, publishers and subscribers. But the HTTP
|
8
|
+
API of RabbitMQ doesn't scale all that well, so that a large number
|
9
|
+
of HTPP calls to set up queue policies can in fact crash a server.
|
10
|
+
|
3
11
|
== Version 2.3.2
|
4
12
|
* config server: fixed a race condition when accessing server state.
|
5
13
|
HTTP requests run in threads separate from the server dispatcher
|
data/Rakefile
CHANGED
@@ -82,6 +82,13 @@ namespace :redis do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
namespace :consul do
|
86
|
+
desc "start consul agent in development mode"
|
87
|
+
task :start do
|
88
|
+
system "consul agent -dev -node machine"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
85
92
|
Cucumber::Rake::Task.new(:cucumber) do |t|
|
86
93
|
t.cucumber_opts = "features --format progress"
|
87
94
|
end
|
@@ -5,6 +5,7 @@ Feature: Redis auto failover
|
|
5
5
|
Background:
|
6
6
|
Given a redis server "redis-1" exists as master
|
7
7
|
And a redis server "redis-2" exists as slave of "redis-1"
|
8
|
+
And consul state has been cleared
|
8
9
|
|
9
10
|
Scenario: Successful redis master switch
|
10
11
|
Given a redis configuration server using redis servers "redis-1,redis-2" with clients "rc-client-1,rc-client-2" exists
|
@@ -1,3 +1,10 @@
|
|
1
|
+
Given /^consul state has been cleared$/ do
|
2
|
+
system "killall beetle beetle_handler >/dev/null 2>/dev/null"
|
3
|
+
system "curl --silent --request PUT http://localhost:8500/v1/kv/apps/beetle/config/ >/dev/null"
|
4
|
+
system "curl --silent --request PUT http://localhost:8500/v1/kv/shared/config/ >/dev/null"
|
5
|
+
system "curl --silent --request DELETE http://localhost:8500/v1/kv/apps/beetle/state/redis_master_file_content >/dev/null"
|
6
|
+
end
|
7
|
+
|
1
8
|
Given /^a redis server "([^\"]*)" exists as master$/ do |redis_name|
|
2
9
|
TestDaemons::Redis[redis_name].restart
|
3
10
|
TestDaemons::Redis[redis_name].master
|
@@ -27,7 +27,7 @@ module TestDaemons
|
|
27
27
|
clients_parameter_string = @@redis_configuration_clients.blank? ? "" : "--client-ids #{@@redis_configuration_clients}"
|
28
28
|
DaemonController.new(
|
29
29
|
:identifier => "Redis configuration test server",
|
30
|
-
:start_command => "./beetle configuration_server -v -d --redis-master-file #{redis_master_file} --redis-servers '#{@@redis_servers}' #{clients_parameter_string} --redis-master-retry-interval 1 --pid-file #{pid_file} --log-file #{log_file} --redis-failover-confidence-level #{@@confidence_level}",
|
30
|
+
:start_command => "./beetle configuration_server -v -d --redis-master-file #{redis_master_file} --redis-servers '#{@@redis_servers}' #{clients_parameter_string} --redis-master-retry-interval 1 --pid-file #{pid_file} --log-file #{log_file} --redis-failover-confidence-level #{@@confidence_level} --consul http://localhost:8500",
|
31
31
|
:ping_command => lambda{ answers_text_requests? },
|
32
32
|
:pid_file => pid_file,
|
33
33
|
:log_file => log_file,
|
data/lib/beetle/base.rb
CHANGED
@@ -12,7 +12,7 @@ module Beetle
|
|
12
12
|
@server = @servers[rand @servers.size]
|
13
13
|
@exchanges = {}
|
14
14
|
@queues = {}
|
15
|
-
@dead_lettering = DeadLettering.new(@client
|
15
|
+
@dead_lettering = DeadLettering.new(@client)
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
@@ -54,7 +54,13 @@ module Beetle
|
|
54
54
|
@queues[@server] ||= {}
|
55
55
|
end
|
56
56
|
|
57
|
-
|
57
|
+
QueueInfo = Struct.new(:queue, :create_policies)
|
58
|
+
|
59
|
+
def queue(name, create_policies: false)
|
60
|
+
info = queues[name]
|
61
|
+
if info && create_policies && !info.create_policies
|
62
|
+
queues.delete(name)
|
63
|
+
end
|
58
64
|
queues[name] ||=
|
59
65
|
begin
|
60
66
|
opts = @client.queues[name]
|
@@ -66,10 +72,11 @@ module Beetle
|
|
66
72
|
@client.bindings[name].each do |binding_options|
|
67
73
|
exchange_name = binding_options[:exchange]
|
68
74
|
binding_options = binding_options.slice(*QUEUE_BINDING_KEYS)
|
69
|
-
the_queue = bind_queue!(queue_name, creation_options, exchange_name, binding_options)
|
75
|
+
the_queue = bind_queue!(queue_name, creation_options, exchange_name, binding_options, create_policies: create_policies)
|
70
76
|
end
|
71
|
-
the_queue
|
77
|
+
info = QueueInfo.new(the_queue, create_policies)
|
72
78
|
end
|
79
|
+
info.queue
|
73
80
|
end
|
74
81
|
|
75
82
|
end
|
data/lib/beetle/client.rb
CHANGED
@@ -73,12 +73,19 @@ module Beetle
|
|
73
73
|
# the name of the exchange this queue will be bound to (defaults to the name of the queue)
|
74
74
|
# [<tt>:key</tt>]
|
75
75
|
# the binding key (defaults to the name of the queue)
|
76
|
+
# [<tt>:lazy</tt>]
|
77
|
+
# whether the queue should use lazy mode (defaults to <tt>config.lazy_queues_enabled</tt>)
|
78
|
+
# [<tt>:dead_lettering</tt>]
|
79
|
+
# whether the queue should use dead lettering (defaults to <tt>config.dead_lettering_enabled</tt>)
|
76
80
|
# automatically registers the specified exchange if it hasn't been registered yet
|
77
81
|
|
78
82
|
def register_queue(name, options={})
|
79
83
|
name = name.to_s
|
80
84
|
raise ConfigurationError.new("queue #{name} already configured") if queues.include?(name)
|
81
|
-
opts = {
|
85
|
+
opts = {
|
86
|
+
:exchange => name, :key => name, :auto_delete => false, :amqp_name => name,
|
87
|
+
:lazy => config.lazy_queues_enabled, :dead_lettering => config.dead_lettering_enabled
|
88
|
+
}.merge!(options.symbolize_keys)
|
82
89
|
opts.merge! :durable => true, :passive => false, :exclusive => false
|
83
90
|
exchange = opts.delete(:exchange).to_s
|
84
91
|
key = opts.delete(:key)
|
@@ -202,6 +209,11 @@ module Beetle
|
|
202
209
|
publisher.purge(queues)
|
203
210
|
end
|
204
211
|
|
212
|
+
# declares all queues, binds them and creates/updates all policies
|
213
|
+
def setup_queues_and_policies(queues)
|
214
|
+
publisher.setup_queues_and_policies(queues)
|
215
|
+
end
|
216
|
+
|
205
217
|
# start listening to all registered queues. Calls #listen_queues internally
|
206
218
|
# runs the given block before entering the eventmachine loop.
|
207
219
|
def listen(_deprecated_messages=nil, &block)
|
@@ -5,29 +5,34 @@ module Beetle
|
|
5
5
|
class DeadLettering
|
6
6
|
class FailedRabbitRequest < StandardError; end
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
attr_reader :client, :config
|
9
|
+
|
10
|
+
def initialize(client)
|
11
|
+
@client = client
|
12
|
+
@config = client.config
|
10
13
|
end
|
11
14
|
|
12
15
|
def bind_dead_letter_queues!(channel, servers, target_queue, creation_keys = {})
|
13
|
-
|
16
|
+
policy_options = client.queues[target_queue].slice(:dead_lettering, :lazy)
|
17
|
+
if policy_options[:dead_lettering]
|
14
18
|
dead_letter_queue_name = dead_letter_queue_name(target_queue)
|
15
|
-
logger.
|
19
|
+
logger.info("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_keys.inspect}")
|
16
20
|
channel.queue(dead_letter_queue_name, creation_keys)
|
17
21
|
end
|
18
22
|
|
19
|
-
if
|
20
|
-
logger.
|
23
|
+
if policy_options[:dead_lettering]
|
24
|
+
logger.info("Beetle: setting #{dead_letter_queue_name} as dead letter queue of #{target_queue} on all servers")
|
21
25
|
end
|
22
|
-
set_queue_policies!(servers, target_queue)
|
26
|
+
set_queue_policies!(servers, target_queue, policy_options)
|
23
27
|
|
24
|
-
if
|
25
|
-
logger.
|
28
|
+
if policy_options[:dead_lettering]
|
29
|
+
logger.info("Beetle: setting #{target_queue} as dead letter queue of #{dead_letter_queue_name} on all servers")
|
26
30
|
set_queue_policies!(
|
27
31
|
servers,
|
28
32
|
dead_letter_queue_name,
|
29
|
-
:message_ttl =>
|
30
|
-
|
33
|
+
{ :message_ttl => config.dead_lettering_msg_ttl,
|
34
|
+
:routing_key => target_queue
|
35
|
+
}.merge(policy_options)
|
31
36
|
)
|
32
37
|
end
|
33
38
|
end
|
@@ -40,21 +45,21 @@ module Beetle
|
|
40
45
|
raise ArgumentError.new("server missing") if server.blank?
|
41
46
|
raise ArgumentError.new("queue name missing") if queue_name.blank?
|
42
47
|
|
43
|
-
return unless
|
48
|
+
return unless options[:dead_lettering] || options[:lazy]
|
44
49
|
|
45
|
-
vhost = CGI.escape(
|
50
|
+
vhost = CGI.escape(config.vhost)
|
46
51
|
request_url = URI("http://#{server}/api/policies/#{vhost}/#{queue_name}_policy")
|
47
52
|
request = Net::HTTP::Put.new(request_url)
|
48
53
|
|
49
54
|
# set up queue policy
|
50
55
|
definition = {}
|
51
|
-
if
|
56
|
+
if options[:dead_lettering]
|
52
57
|
definition["dead-letter-routing-key"] = dead_letter_routing_key(queue_name, options)
|
53
58
|
definition["dead-letter-exchange"] = ""
|
54
59
|
definition["message-ttl"] = options[:message_ttl] if options[:message_ttl]
|
55
60
|
end
|
56
61
|
|
57
|
-
definition["queue-mode"] = "lazy" if
|
62
|
+
definition["queue-mode"] = "lazy" if options[:lazy]
|
58
63
|
|
59
64
|
request_body = {
|
60
65
|
"pattern" => "^#{queue_name}$",
|
@@ -84,9 +89,9 @@ module Beetle
|
|
84
89
|
end
|
85
90
|
|
86
91
|
def run_rabbit_http_request(uri, request, &block)
|
87
|
-
request.basic_auth(
|
92
|
+
request.basic_auth(config.user, config.password)
|
88
93
|
request["Content-Type"] = "application/json"
|
89
|
-
Net::HTTP.start(uri.hostname,
|
94
|
+
Net::HTTP.start(uri.hostname, config.api_port, :read_timeout => config.dead_lettering_read_timeout) do |http|
|
90
95
|
block.call(http) if block_given?
|
91
96
|
end
|
92
97
|
end
|
@@ -98,7 +103,7 @@ module Beetle
|
|
98
103
|
end
|
99
104
|
|
100
105
|
def logger
|
101
|
-
|
106
|
+
config.logger
|
102
107
|
end
|
103
108
|
end
|
104
109
|
end
|
data/lib/beetle/publisher.rb
CHANGED
@@ -143,6 +143,14 @@ module Beetle
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
+
def setup_queues_and_policies(queue_names) #:nodoc:
|
147
|
+
each_server do
|
148
|
+
queue_names.each do |name|
|
149
|
+
queue(name, create_policies: true)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
146
154
|
def stop #:nodoc:
|
147
155
|
each_server { stop! }
|
148
156
|
end
|
@@ -214,10 +222,12 @@ module Beetle
|
|
214
222
|
end
|
215
223
|
|
216
224
|
# TODO: Refactor, fetch the keys and stuff itself
|
217
|
-
def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
|
225
|
+
def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys, create_policies: false)
|
218
226
|
logger.debug("Beetle: creating queue with opts: #{creation_keys.inspect}")
|
219
227
|
queue = bunny.queue(queue_name, creation_keys)
|
220
|
-
|
228
|
+
if create_policies
|
229
|
+
@dead_lettering.bind_dead_letter_queues!(bunny, @client.servers, queue_name, creation_keys)
|
230
|
+
end
|
221
231
|
logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_keys.inspect}")
|
222
232
|
queue.bind(exchange(exchange_name), binding_keys)
|
223
233
|
queue
|
data/lib/beetle/subscriber.rb
CHANGED
@@ -144,19 +144,19 @@ module Beetle
|
|
144
144
|
callback = create_subscription_callback(queue_name, amqp_queue_name, handler, opts)
|
145
145
|
keys = opts.slice(*SUBSCRIPTION_KEYS).merge(:key => "#", :ack => true)
|
146
146
|
logger.debug "Beetle: subscribing to queue #{amqp_queue_name} with key # on server #{@server}"
|
147
|
-
queues[queue_name].subscribe(keys, &callback)
|
147
|
+
queues[queue_name].queue.subscribe(keys, &callback)
|
148
148
|
subscriptions[queue_name] = [keys, callback]
|
149
149
|
end
|
150
150
|
|
151
151
|
def pause(queue_name)
|
152
|
-
return unless queues[queue_name].subscribed?
|
153
|
-
queues[queue_name].unsubscribe
|
152
|
+
return unless queues[queue_name].queue.subscribed?
|
153
|
+
queues[queue_name].queue.unsubscribe
|
154
154
|
end
|
155
155
|
|
156
156
|
def resume(queue_name)
|
157
|
-
return if queues[queue_name].subscribed?
|
157
|
+
return if queues[queue_name].queue.subscribed?
|
158
158
|
keys, callback = subscriptions[queue_name]
|
159
|
-
queues[queue_name].subscribe(keys, &callback)
|
159
|
+
queues[queue_name].queue.subscribe(keys, &callback)
|
160
160
|
end
|
161
161
|
|
162
162
|
def create_subscription_callback(queue_name, amqp_queue_name, handler, opts)
|
@@ -204,10 +204,12 @@ module Beetle
|
|
204
204
|
channel.__send__(opts[:type], name, opts.slice(*EXCHANGE_CREATION_KEYS))
|
205
205
|
end
|
206
206
|
|
207
|
-
def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
|
207
|
+
def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys, create_policies: false)
|
208
208
|
queue = channel.queue(queue_name, creation_keys)
|
209
209
|
target_servers = @client.servers + @client.additional_subscription_servers
|
210
|
-
|
210
|
+
if create_policies
|
211
|
+
@dead_lettering.bind_dead_letter_queues!(channel, target_servers, queue_name, creation_keys)
|
212
|
+
end
|
211
213
|
exchange = exchange(exchange_name)
|
212
214
|
queue.bind(exchange, binding_keys)
|
213
215
|
queue
|
data/lib/beetle/version.rb
CHANGED
data/test/beetle/client_test.rb
CHANGED
@@ -79,7 +79,7 @@ module Beetle
|
|
79
79
|
|
80
80
|
test "registering a queue should store it in the configuration with symbolized option keys and force durable=true and passive=false and set the amqp queue name" do
|
81
81
|
@client.register_queue("some_queue", "durable" => false, "exchange" => "some_exchange")
|
82
|
-
assert_equal({:durable => true, :passive => false, :auto_delete => false, :exclusive => false, :amqp_name => "some_queue"}, @client.queues["some_queue"])
|
82
|
+
assert_equal({:durable => true, :passive => false, :lazy=>false, :dead_lettering=>false, :auto_delete => false, :exclusive => false, :amqp_name => "some_queue"}, @client.queues["some_queue"])
|
83
83
|
end
|
84
84
|
|
85
85
|
test "registering a queue should add the queue to the list of queues of the queue's exchange" do
|
@@ -308,6 +308,13 @@ module Beetle
|
|
308
308
|
assert_equal "ha!", client.purge(:queue1, :queue2)
|
309
309
|
end
|
310
310
|
|
311
|
+
test "should delegate queue setup to the publisher instance" do
|
312
|
+
client = Client.new
|
313
|
+
client.register_queue(:queue)
|
314
|
+
client.send(:publisher).expects(:setup_queues_and_policies).with(["queue"]).returns("ha!")
|
315
|
+
assert_equal "ha!", client.setup_queues_and_policies(["queue"])
|
316
|
+
end
|
317
|
+
|
311
318
|
test "should delegate rpc calls to the publisher instance" do
|
312
319
|
client = Client.new
|
313
320
|
client.register_message("deadletter")
|
@@ -4,7 +4,8 @@ module Beetle
|
|
4
4
|
class SetDeadLetteringsTest < Minitest::Test
|
5
5
|
def setup
|
6
6
|
@config = Configuration.new
|
7
|
-
@
|
7
|
+
@client = Client.new @config
|
8
|
+
@dead_lettering = DeadLettering.new(@client)
|
8
9
|
@config.dead_lettering_enabled = true
|
9
10
|
end
|
10
11
|
|
@@ -25,9 +26,9 @@ module Beetle
|
|
25
26
|
@server = "localhost:15672"
|
26
27
|
@queue_name = "QUEUE_NAME"
|
27
28
|
@config = Configuration.new
|
29
|
+
@client = Client.new @config
|
28
30
|
@config.logger = Logger.new("/dev/null")
|
29
|
-
@dead_lettering = DeadLettering.new(@
|
30
|
-
@config.dead_lettering_enabled = true
|
31
|
+
@dead_lettering = DeadLettering.new(@client)
|
31
32
|
end
|
32
33
|
|
33
34
|
test "raises exception when queue name wasn't specified" do
|
@@ -55,12 +56,10 @@ module Beetle
|
|
55
56
|
}}.to_json)
|
56
57
|
.to_return(:status => 204)
|
57
58
|
|
58
|
-
@dead_lettering.set_queue_policy!(@server, @queue_name)
|
59
|
+
@dead_lettering.set_queue_policy!(@server, @queue_name, :lazy => false, :dead_lettering => true)
|
59
60
|
end
|
60
61
|
|
61
62
|
test "creates a policy by posting to the rabbitmq if lazy queues are enabled" do
|
62
|
-
@config.lazy_queues_enabled = true
|
63
|
-
@config.dead_lettering_enabled = false
|
64
63
|
stub_request(:put, "http://localhost:15672/api/policies/%2F/QUEUE_NAME_policy")
|
65
64
|
.with(basic_auth: ['guest', 'guest'])
|
66
65
|
.with(:body => {
|
@@ -72,7 +71,7 @@ module Beetle
|
|
72
71
|
}}.to_json)
|
73
72
|
.to_return(:status => 204)
|
74
73
|
|
75
|
-
@dead_lettering.set_queue_policy!(@server, @queue_name)
|
74
|
+
@dead_lettering.set_queue_policy!(@server, @queue_name, :lazy => true, :dead_lettering => false)
|
76
75
|
end
|
77
76
|
|
78
77
|
test "raises exception when policy couldn't successfully be created" do
|
@@ -81,7 +80,7 @@ module Beetle
|
|
81
80
|
.to_return(:status => [405])
|
82
81
|
|
83
82
|
assert_raises DeadLettering::FailedRabbitRequest do
|
84
|
-
@dead_lettering.set_queue_policy!(@server, @queue_name)
|
83
|
+
@dead_lettering.set_queue_policy!(@server, @queue_name, :lazy => true, :dead_lettering => true)
|
85
84
|
end
|
86
85
|
end
|
87
86
|
|
@@ -99,7 +98,7 @@ module Beetle
|
|
99
98
|
}}.to_json)
|
100
99
|
.to_return(:status => 204)
|
101
100
|
|
102
|
-
@dead_lettering.set_queue_policy!(@server, @queue_name, :message_ttl => 10000)
|
101
|
+
@dead_lettering.set_queue_policy!(@server, @queue_name, :dead_lettering => true, :message_ttl => 10000)
|
103
102
|
end
|
104
103
|
|
105
104
|
test "properly encodes the vhost from the configuration" do
|
@@ -117,7 +116,7 @@ module Beetle
|
|
117
116
|
|
118
117
|
@config.vhost = "foo/"
|
119
118
|
|
120
|
-
@dead_lettering.set_queue_policy!(@server, @queue_name)
|
119
|
+
@dead_lettering.set_queue_policy!(@server, @queue_name, :dead_lettering => true)
|
121
120
|
end
|
122
121
|
end
|
123
122
|
|
@@ -125,28 +124,31 @@ module Beetle
|
|
125
124
|
def setup
|
126
125
|
@queue_name = "QUEUE_NAME"
|
127
126
|
@config = Configuration.new
|
127
|
+
@client = Client.new @config
|
128
128
|
@config.logger = Logger.new("/dev/null")
|
129
|
-
@dead_lettering = DeadLettering.new(@
|
129
|
+
@dead_lettering = DeadLettering.new(@client)
|
130
130
|
@servers = ["localhost:55672"]
|
131
131
|
end
|
132
132
|
|
133
133
|
test "is does not call out to rabbit if neither dead lettering nor lazy queues are enabled" do
|
134
|
-
@
|
134
|
+
@client.register_queue(@queue_name, :dead_lettering => false, :lazy => false)
|
135
135
|
channel = stub('channel')
|
136
136
|
@dead_lettering.expects(:run_rabbit_http_request).never
|
137
137
|
@dead_lettering.bind_dead_letter_queues!(channel, @servers, @queue_name)
|
138
138
|
end
|
139
139
|
|
140
140
|
test "creates and connects the dead letter queue via policies when enabled" do
|
141
|
-
@
|
141
|
+
@client.register_queue(@queue_name, :dead_lettering => true, :lazy => false)
|
142
142
|
|
143
143
|
channel = stub('channel')
|
144
144
|
|
145
145
|
channel.expects(:queue).with("#{@queue_name}_dead_letter", {})
|
146
|
-
@dead_lettering.expects(:set_queue_policies!).with(@servers, @queue_name)
|
146
|
+
@dead_lettering.expects(:set_queue_policies!).with(@servers, @queue_name, :dead_lettering => true, :lazy => false)
|
147
147
|
@dead_lettering.expects(:set_queue_policies!).with(@servers, "#{@queue_name}_dead_letter",
|
148
148
|
:routing_key => @queue_name,
|
149
|
-
:message_ttl => 1000
|
149
|
+
:message_ttl => 1000,
|
150
|
+
:dead_lettering => true,
|
151
|
+
:lazy => false
|
150
152
|
)
|
151
153
|
|
152
154
|
@dead_lettering.bind_dead_letter_queues!(channel, @servers, @queue_name)
|
@@ -273,6 +273,19 @@ module Beetle
|
|
273
273
|
end
|
274
274
|
|
275
275
|
test "binding a queue should create it using the config and bind it to the exchange with the name specified" do
|
276
|
+
@client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#", :arguments => {"foo" => "fighter"})
|
277
|
+
@pub.expects(:exchange).with("some_exchange").returns(:the_exchange)
|
278
|
+
q = mock("queue")
|
279
|
+
q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
|
280
|
+
m = mock("Bunny")
|
281
|
+
m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"foo" => "fighter"}).returns(q)
|
282
|
+
@pub.expects(:bunny).returns(m)
|
283
|
+
|
284
|
+
@pub.send(:queue, "some_queue")
|
285
|
+
assert_equal Base::QueueInfo.new(q, false), @pub.send(:queues)["some_queue"]
|
286
|
+
end
|
287
|
+
|
288
|
+
test "binding a queue should create it using the config and bind it to the exchange with the name specified and setup policies if requested" do
|
276
289
|
@client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#", :arguments => {"foo" => "fighter"})
|
277
290
|
@pub.expects(:exchange).with("some_exchange").returns(:the_exchange)
|
278
291
|
q = mock("queue")
|
@@ -281,8 +294,29 @@ module Beetle
|
|
281
294
|
m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"foo" => "fighter"}).returns(q)
|
282
295
|
@pub.expects(:bunny).returns(m).twice
|
283
296
|
|
297
|
+
@pub.send(:queue, "some_queue", create_policies: true)
|
298
|
+
assert_equal Base::QueueInfo.new(q, true), @pub.send(:queues)["some_queue"]
|
299
|
+
end
|
300
|
+
|
301
|
+
test "binding a queue with create_plocies: true after having already declared it with create_plocies: false creates the policies" do
|
302
|
+
@client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#", :arguments => {"foo" => "fighter"})
|
303
|
+
@pub.expects(:exchange).with("some_exchange").returns(:the_exchange)
|
304
|
+
q = mock("queue")
|
305
|
+
q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
|
306
|
+
m = mock("Bunny")
|
307
|
+
m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"foo" => "fighter"}).returns(q)
|
308
|
+
@pub.expects(:bunny).returns(m)
|
309
|
+
|
284
310
|
@pub.send(:queue, "some_queue")
|
285
|
-
assert_equal q, @pub.send(:queues)["some_queue"]
|
311
|
+
assert_equal Base::QueueInfo.new(q, false), @pub.send(:queues)["some_queue"]
|
312
|
+
|
313
|
+
@pub.expects(:exchange).with("some_exchange").returns(:the_exchange)
|
314
|
+
q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
|
315
|
+
m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"foo" => "fighter"}).returns(q)
|
316
|
+
@pub.expects(:bunny).returns(m).twice
|
317
|
+
|
318
|
+
@pub.send(:queue, "some_queue", create_policies: true)
|
319
|
+
assert_equal Base::QueueInfo.new(q, true), @pub.send(:queues)["some_queue"]
|
286
320
|
end
|
287
321
|
|
288
322
|
test "should bind the defined queues for the used exchanges when publishing" do
|
@@ -325,6 +359,18 @@ module Beetle
|
|
325
359
|
queue.expects(:purge).in_sequence(s)
|
326
360
|
@pub.purge(["queue"])
|
327
361
|
end
|
362
|
+
|
363
|
+
test "setting up queues and policies should iterate over all servers" do
|
364
|
+
@pub.servers = %w(a b)
|
365
|
+
queue = mock("queue")
|
366
|
+
s = sequence("setup")
|
367
|
+
@pub.expects(:set_current_server).with("a").in_sequence(s)
|
368
|
+
@pub.expects(:queue).with("queue", :create_policies => true).returns(queue).in_sequence(s)
|
369
|
+
@pub.expects(:set_current_server).with("b").in_sequence(s)
|
370
|
+
@pub.expects(:queue).with("queue", :create_policies => true).returns(queue).in_sequence(s)
|
371
|
+
@pub.setup_queues_and_policies(["queue"])
|
372
|
+
end
|
373
|
+
|
328
374
|
end
|
329
375
|
|
330
376
|
class PublisherExchangeManagementTest < Minitest::Test
|
@@ -89,7 +89,7 @@ module Beetle
|
|
89
89
|
q = mock("queue a")
|
90
90
|
q.expects(:subscribed?).returns(true)
|
91
91
|
q.expects(:unsubscribe)
|
92
|
-
@sub.stubs(:queues).returns({"a" =>q})
|
92
|
+
@sub.stubs(:queues).returns({"a" => Base::QueueInfo.new(q,false)})
|
93
93
|
@sub.__send__(:pause, "a")
|
94
94
|
end
|
95
95
|
|
@@ -97,7 +97,7 @@ module Beetle
|
|
97
97
|
q = mock("queue a")
|
98
98
|
q.expects(:subscribed?).returns(false)
|
99
99
|
q.expects(:unsubscribe).never
|
100
|
-
@sub.stubs(:queues).returns({"a" =>q})
|
100
|
+
@sub.stubs(:queues).returns({"a" => Base::QueueInfo.new(q,false)})
|
101
101
|
@sub.__send__(:pause, "a")
|
102
102
|
end
|
103
103
|
|
@@ -105,7 +105,7 @@ module Beetle
|
|
105
105
|
q = mock("queue a")
|
106
106
|
q.expects(:subscribed?).returns(false)
|
107
107
|
q.expects(:subscribe)
|
108
|
-
@sub.stubs(:queues).returns({"a" =>q})
|
108
|
+
@sub.stubs(:queues).returns({"a" => Base::QueueInfo.new(q,false)})
|
109
109
|
@sub.__send__(:resume, "a")
|
110
110
|
end
|
111
111
|
|
@@ -113,7 +113,7 @@ module Beetle
|
|
113
113
|
q = mock("queue a")
|
114
114
|
q.expects(:subscribed?).returns(true)
|
115
115
|
q.expects(:subscribe).never
|
116
|
-
@sub.stubs(:queues).returns({"a" =>q})
|
116
|
+
@sub.stubs(:queues).returns({"a" => Base::QueueInfo.new(q,false)})
|
117
117
|
@sub.__send__(:resume, "a")
|
118
118
|
end
|
119
119
|
|
@@ -150,10 +150,23 @@ module Beetle
|
|
150
150
|
q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
|
151
151
|
m = mock("MQ")
|
152
152
|
m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"schmu" => 5}).returns(q)
|
153
|
-
@sub.expects(:channel).returns(m)
|
153
|
+
@sub.expects(:channel).returns(m)
|
154
154
|
|
155
155
|
@sub.send(:queue, "some_queue")
|
156
|
-
assert_equal q, @sub.send(:queues)["some_queue"]
|
156
|
+
assert_equal q, @sub.send(:queues)["some_queue"].queue
|
157
|
+
end
|
158
|
+
|
159
|
+
test "binding a queue should create it using the config and bind it to the exchange with the name specified and create policies if requested" do
|
160
|
+
@client.register_queue("some_queue", "durable" => true, "exchange" => "some_exchange", "key" => "haha.#", "arguments" => {"schmu" => 5})
|
161
|
+
@sub.expects(:exchange).with("some_exchange").returns(:the_exchange)
|
162
|
+
q = mock("queue")
|
163
|
+
q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
|
164
|
+
m = mock("MQ")
|
165
|
+
m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"schmu" => 5}).returns(q)
|
166
|
+
@sub.expects(:channel).returns(m).twice
|
167
|
+
|
168
|
+
@sub.send(:queue, "some_queue", create_policies: true)
|
169
|
+
assert_equal q, @sub.send(:queues)["some_queue"].queue
|
157
170
|
end
|
158
171
|
|
159
172
|
test "binding queues should bind all queues" do
|
@@ -357,7 +370,7 @@ module Beetle
|
|
357
370
|
q = mock("QUEUE")
|
358
371
|
subscription_options = {:ack => true, :key => "#"}
|
359
372
|
q.expects(:subscribe).with(subscription_options).yields(header, "foo")
|
360
|
-
@sub.expects(:queues).returns({"some_queue" => q}).once
|
373
|
+
@sub.expects(:queues).returns({"some_queue" => Base::QueueInfo.new(q,false)}).once
|
361
374
|
@sub.send(:subscribe, "some_queue")
|
362
375
|
assert block_called
|
363
376
|
assert @sub.__send__(:has_subscription?, "some_queue")
|
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:
|
4
|
+
version: 3.0.0.rc1
|
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: 2019-
|
15
|
+
date: 2019-04-26 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bunny
|
@@ -322,7 +322,6 @@ files:
|
|
322
322
|
- examples/headers.rb
|
323
323
|
- examples/multiple_exchanges.rb
|
324
324
|
- examples/multiple_queues.rb
|
325
|
-
- examples/murks.rb
|
326
325
|
- examples/nonexistent_server.rb
|
327
326
|
- examples/pause_and_resume.rb
|
328
327
|
- examples/publish_many_messages.rb
|
data/examples/murks.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'bunny'
|
2
|
-
|
3
|
-
conn = Bunny.new
|
4
|
-
conn.start
|
5
|
-
|
6
|
-
# consumer
|
7
|
-
ch = conn.create_channel
|
8
|
-
x = ch.topic("echo")
|
9
|
-
q1 = ch.queue("echo").bind(x, :routing_key => "#")
|
10
|
-
|
11
|
-
consumer = q1.subscribe do |delivery_info, properties, payload|
|
12
|
-
puts delivery_info.inspect, properties.inspect, payload.inspect
|
13
|
-
ch.default_exchange.publish(payload.to_s, :routing_key => properties[:reply_to])
|
14
|
-
end
|
15
|
-
|
16
|
-
# publisher
|
17
|
-
q2 = ch.queue()
|
18
|
-
puts "reply queue: #{q2.name}"
|
19
|
-
x.publish("Hello, everybody!", :routing_key => "echo", :reply_to => q2.name)
|
20
|
-
|
21
|
-
sleep 1
|
22
|
-
|
23
|
-
delivery_info, properties, payload = q2.pop
|
24
|
-
|
25
|
-
puts "This is the message: " + payload.inspect
|
26
|
-
puts delivery_info.inspect, properties.inspect
|
27
|
-
|
28
|
-
consumer.cancel
|
29
|
-
ch.close
|
30
|
-
conn.close
|