beetle 2.3.2 → 3.0.0.rc1
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/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
|