beetle 3.0.0.rc1 → 3.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 299657b394d85d53b70417554db9a3ca53de5339dc0fc777e1555536237ccf1b
4
- data.tar.gz: a4fda19185d645fbb26e563b7b7c72ffe67d03ef3cc621a581b7b1cee38b3178
3
+ metadata.gz: fb0489f8580ec11b65b79718c9e76c0f4b26a14af2fbbf471cf4b630fca5fa7d
4
+ data.tar.gz: 0f3ef313bfaf103eecfd1c1714c5d28b6ec10bc7ce0313e55f0cee6e00f2086a
5
5
  SHA512:
6
- metadata.gz: 3b6c98dd094e445db0424aab1c992eb9245df6fb4e402c45d087c8ca395c9bfd2f3ec57d95999a79ce5f4853d1c02e139a829b962f6cef896c73004a299743ad
7
- data.tar.gz: 1324bd1753c97574cf0dd657f7096be41e26d76f271525c124aa198286056cbd8673bf5ff0894bc761b94351cdd14d1dbd3504e3925fcc6e11804f6ae99b19dd
6
+ metadata.gz: 51aa8c7058c8149daa6c2d69c1ae8a26731957290f06e4bde26a06613e260030f9cb16d286415958db74afcb38bdc74a9ccacc58643ceb25227662a800fada22
7
+ data.tar.gz: ae1eed22b04f81c612aff1ad88836e57df2db997a923da8f1819d8675093a9533f377e6429928049f9665b5a7548cdbbfb48172ddfbb361bac2e2adbcfba507b
@@ -1,12 +1,21 @@
1
1
  = Release Notes
2
2
 
3
+ == Version 3.0.0.rc2
4
+ * change policy setup to be asynchronous, on demand in publisher and
5
+ consumer. Users have to run a processors to listen to messages and
6
+ call setup_queue_policies! with the parses JSON paylod of the
7
+ message.
8
+ * added dump_expiries command to beetle to dump dediplication store
9
+ expiry times.
10
+ * added delete_queue_keys command to beetle to allow deletion of
11
+ excess dedup store entries for a given queue.
3
12
 
4
13
  == Version 3.0.0.rc1
5
14
  * provide client method to setup queues and queue policies.
6
15
  Setting up queue policies on demand in publisher and subscriber is OK
7
16
  for a small number of queues, publishers and subscribers. But the HTTP
8
17
  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.
18
+ of HTTP calls to set up queue policies can in fact crash a server.
10
19
 
11
20
  == Version 2.3.2
12
21
  * config server: fixed a race condition when accessing server state.
@@ -144,7 +144,7 @@ Then /^the redis master of the beetle handler should be "([^\"]*)"$/ do |redis_n
144
144
  Beetle.config.servers = "127.0.0.1:5672" # rabbitmq
145
145
  Beetle.config.logger.level = Logger::INFO
146
146
  client = Beetle::Client.new.configure :auto_delete => true do |config|
147
- config.queue(:echo)
147
+ config.queue(:echo, :lazy => true, :dead_lettering => true)
148
148
  config.message(:echo)
149
149
  end
150
150
  assert_match /#{TestDaemons::Redis[redis_name].ip_with_port}/, client.rpc(:echo, 'nil').second
@@ -3,6 +3,7 @@
3
3
  require "rubygems"
4
4
  require "daemons"
5
5
  require "optparse"
6
+ require 'json'
6
7
  require File.expand_path("../../lib/beetle", File.dirname(__FILE__))
7
8
 
8
9
  tmp_path = File.expand_path("../../tmp", File.dirname(__FILE__))
@@ -22,7 +23,7 @@ Daemons.run_proc("beetle_handler", :log_output => true, :dir_mode => :normal, :d
22
23
  Beetle.config.logger.level = Logger::INFO
23
24
 
24
25
  client = Beetle::Client.new.configure :auto_delete => true do |config|
25
- config.queue(:echo)
26
+ config.queue(:echo, :lazy => true, :dead_lettering => true)
26
27
  config.message(:echo)
27
28
  config.handler(:echo) do |message|
28
29
  begin
@@ -32,6 +33,14 @@ Daemons.run_proc("beetle_handler", :log_output => true, :dir_mode => :normal, :d
32
33
  "no redis master: exception: #{$!.class}(#{$!}), master_file: '#{master_file_content}'"
33
34
  end
34
35
  end
36
+ config.handler(Beetle.config.beetle_policy_updates_queue_name) do |message|
37
+ begin
38
+ Beetle.config.logger.info "received beetle policy update message': #{message.data}"
39
+ client.set_queue_policies!(JSON.parse(message.data))
40
+ rescue => e
41
+ Beetle.config.logger.error("#{e}:#{e.backtrace.join("\n")}")
42
+ end
43
+ end
35
44
  end
36
45
  client.listen do
37
46
  puts "Started beetle handler for system: #{Beetle.config.system_name}"
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Beetle
2
4
  # Abstract base class shared by Publisher and Subscriber
3
5
  class Base
@@ -12,7 +14,6 @@ module Beetle
12
14
  @server = @servers[rand @servers.size]
13
15
  @exchanges = {}
14
16
  @queues = {}
15
- @dead_lettering = DeadLettering.new(@client)
16
17
  end
17
18
 
18
19
  private
@@ -54,13 +55,7 @@ module Beetle
54
55
  @queues[@server] ||= {}
55
56
  end
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
+ def queue(name)
64
59
  queues[name] ||=
65
60
  begin
66
61
  opts = @client.queues[name]
@@ -72,11 +67,37 @@ module Beetle
72
67
  @client.bindings[name].each do |binding_options|
73
68
  exchange_name = binding_options[:exchange]
74
69
  binding_options = binding_options.slice(*QUEUE_BINDING_KEYS)
75
- the_queue = bind_queue!(queue_name, creation_options, exchange_name, binding_options, create_policies: create_policies)
70
+ the_queue = bind_queue!(queue_name, creation_options, exchange_name, binding_options)
76
71
  end
77
- info = QueueInfo.new(the_queue, create_policies)
72
+ the_queue
78
73
  end
79
- info.queue
74
+ end
75
+
76
+ def bind_dead_letter_queue!(channel, target_queue, creation_keys = {})
77
+ policy_options = @client.queues[target_queue].slice(:dead_lettering, :lazy)
78
+ dead_letter_queue_name = "#{target_queue}_dead_letter"
79
+ if policy_options[:dead_lettering]
80
+ logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_keys.inspect}")
81
+ channel.queue(dead_letter_queue_name, creation_keys)
82
+ end
83
+ return {
84
+ :queue_name => target_queue,
85
+ :dead_letter_queue_name => dead_letter_queue_name,
86
+ :message_ttl => @client.config.dead_lettering_msg_ttl,
87
+ }.merge(policy_options)
88
+ end
89
+
90
+ # called by <tt>bind_queue!</tt>
91
+ def publish_policy_options(options)
92
+ # avoid endless recursion
93
+ return if options[:queue_name] == @client.config.beetle_policy_updates_queue_name
94
+ payload = options.merge(:server => @server)
95
+ logger.debug("Beetle: publishing policy options on #{@server}: #{payload.inspect}")
96
+ # make sure to declare the queue, so the message does not get lost
97
+ queue(@client.config.beetle_policy_updates_queue_name)
98
+ data = payload.to_json
99
+ opts = Message.publishing_options(:key => @client.config.beetle_policy_updates_routing_key, :persistent => true, :redundant => false)
100
+ exchange(@client.config.beetle_policy_exchange_name).publish(data, opts)
80
101
  end
81
102
 
82
103
  end
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Beetle
2
4
  # This class provides the interface through which messaging is configured for both
3
5
  # message producers and consumers. It keeps references to an instance of a
@@ -53,7 +55,17 @@ module Beetle
53
55
  @messages = {}
54
56
  @bindings = {}
55
57
  @deduplication_store = DeduplicationStore.new(config)
58
+ @dead_lettering = DeadLettering.new(config)
56
59
  load_brokers_from_config
60
+ register_exchange(config.beetle_policy_exchange_name)
61
+ # make sure dead lettering is false for the policy update queue
62
+ register_queue(
63
+ config.beetle_policy_updates_queue_name,
64
+ :exchange => config.beetle_policy_exchange_name,
65
+ :key => config.beetle_policy_updates_routing_key,
66
+ :dead_lettering => false,
67
+ :lazy => false,
68
+ )
57
69
  end
58
70
 
59
71
  # register an exchange with the given _name_ and a set of _options_:
@@ -209,11 +221,6 @@ module Beetle
209
221
  publisher.purge(queues)
210
222
  end
211
223
 
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
-
217
224
  # start listening to all registered queues. Calls #listen_queues internally
218
225
  # runs the given block before entering the eventmachine loop.
219
226
  def listen(_deprecated_messages=nil, &block)
@@ -292,6 +299,10 @@ module Beetle
292
299
  @subscriber = nil
293
300
  end
294
301
 
302
+ def set_queue_policies!(message_payload)
303
+ @dead_lettering.set_queue_policies!(message_payload)
304
+ end
305
+
295
306
  private
296
307
 
297
308
  def determine_queue_names(queues)
@@ -5,6 +5,14 @@ module Beetle
5
5
  class Configuration
6
6
  # system name (used for redis cluster partitioning) (defaults to <tt>system</tt>)
7
7
  attr_accessor :system_name
8
+ # system_exchange_name is the name of the exchange on which to publish system internal messages, such as
9
+ # messages to set up queue policies. Whenever a queue is declared in the client, either by publisher or
10
+ # consumer, a message with the queue policy parameters is sent to this exachange. (defaults to <tt>beetle</tt>)
11
+ attr_accessor :beetle_policy_exchange_name
12
+ # Name of the policy update queue
13
+ attr_accessor :beetle_policy_updates_queue_name
14
+ # Name of the policy update routing key
15
+ attr_accessor :beetle_policy_updates_routing_key
8
16
  # default logger (defaults to <tt>Logger.new(log_file)</tt>)
9
17
  attr_accessor :logger
10
18
  # defaults to <tt>STDOUT</tt>
@@ -120,6 +128,9 @@ module Beetle
120
128
 
121
129
  def initialize #:nodoc:
122
130
  self.system_name = "system"
131
+ self.beetle_policy_exchange_name = "beetle-policies"
132
+ self.beetle_policy_updates_queue_name = "beetle-policy-updates"
133
+ self.beetle_policy_updates_routing_key = "beetle.policy.update"
123
134
 
124
135
  self.gc_threshold = 1.hour.to_i
125
136
  self.redis_server = "localhost:6379"
@@ -5,56 +5,44 @@ module Beetle
5
5
  class DeadLettering
6
6
  class FailedRabbitRequest < StandardError; end
7
7
 
8
- attr_reader :client, :config
8
+ attr_reader :config
9
9
 
10
- def initialize(client)
11
- @client = client
12
- @config = client.config
10
+ def initialize(config)
11
+ @config = config
13
12
  end
14
13
 
15
- def bind_dead_letter_queues!(channel, servers, target_queue, creation_keys = {})
16
- policy_options = client.queues[target_queue].slice(:dead_lettering, :lazy)
17
- if policy_options[:dead_lettering]
18
- dead_letter_queue_name = dead_letter_queue_name(target_queue)
19
- logger.info("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_keys.inspect}")
20
- channel.queue(dead_letter_queue_name, creation_keys)
21
- end
14
+ def set_queue_policies!(options)
15
+ # logger.debug "Setting queue policies: #{options.inspect}"
16
+ options = options.symbolize_keys
17
+ server = options[:server]
18
+ target_queue = options[:queue_name]
19
+ dead_letter_queue_name = options[:dead_letter_queue_name]
20
+ policy_options = options.slice(:lazy, :dead_lettering)
22
21
 
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")
25
- end
26
- set_queue_policies!(servers, target_queue, policy_options)
27
-
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")
30
- set_queue_policies!(
31
- servers,
32
- dead_letter_queue_name,
33
- { :message_ttl => config.dead_lettering_msg_ttl,
34
- :routing_key => target_queue
35
- }.merge(policy_options)
36
- )
37
- end
38
- end
22
+ target_queue_options = policy_options.merge(:routing_key => dead_letter_queue_name)
23
+ set_queue_policy!(server, target_queue, target_queue_options)
39
24
 
40
- def set_queue_policies!(servers, queue_name, options={})
41
- servers.each { |server| set_queue_policy!(server, queue_name, options) }
25
+ dead_letter_queue_options = policy_options.merge(:routing_key => target_queue, :message_ttl => options[:message_ttl])
26
+ set_queue_policy!(server, dead_letter_queue_name, dead_letter_queue_options)
42
27
  end
43
28
 
44
29
  def set_queue_policy!(server, queue_name, options={})
30
+ logger.info "Setting queue policy: #{server}, #{queue_name}, #{options.inspect}"
31
+
45
32
  raise ArgumentError.new("server missing") if server.blank?
46
33
  raise ArgumentError.new("queue name missing") if queue_name.blank?
47
34
 
48
35
  return unless options[:dead_lettering] || options[:lazy]
49
36
 
50
37
  vhost = CGI.escape(config.vhost)
38
+ # no need to worry that the server has the port 5672. Net:HTTP will take care of this. See below.
51
39
  request_url = URI("http://#{server}/api/policies/#{vhost}/#{queue_name}_policy")
52
40
  request = Net::HTTP::Put.new(request_url)
53
41
 
54
42
  # set up queue policy
55
43
  definition = {}
56
44
  if options[:dead_lettering]
57
- definition["dead-letter-routing-key"] = dead_letter_routing_key(queue_name, options)
45
+ definition["dead-letter-routing-key"] = options[:routing_key]
58
46
  definition["dead-letter-exchange"] = ""
59
47
  definition["message-ttl"] = options[:message_ttl] if options[:message_ttl]
60
48
  end
@@ -80,19 +68,15 @@ module Beetle
80
68
  :ok
81
69
  end
82
70
 
83
- def dead_letter_routing_key(queue_name, options)
84
- options.fetch(:routing_key) { dead_letter_queue_name(queue_name) }
85
- end
86
-
87
- def dead_letter_queue_name(queue_name)
88
- "#{queue_name}_dead_letter"
89
- end
90
-
91
71
  def run_rabbit_http_request(uri, request, &block)
92
72
  request.basic_auth(config.user, config.password)
93
73
  request["Content-Type"] = "application/json"
94
- Net::HTTP.start(uri.hostname, config.api_port, :read_timeout => config.dead_lettering_read_timeout) do |http|
95
- block.call(http) if block_given?
74
+ http = Net::HTTP.new(uri.hostname, config.api_port)
75
+ http.read_timeout = config.dead_lettering_read_timeout
76
+ # don't do this in production:
77
+ # http.set_debug_output(logger.instance_eval{ @logdev.dev })
78
+ http.start do |instance|
79
+ block.call(instance) if block_given?
96
80
  end
97
81
  end
98
82
 
@@ -103,7 +87,8 @@ module Beetle
103
87
  end
104
88
 
105
89
  def logger
106
- config.logger
90
+ @config.logger
107
91
  end
92
+
108
93
  end
109
94
  end
@@ -222,14 +222,13 @@ module Beetle
222
222
  end
223
223
 
224
224
  # TODO: Refactor, fetch the keys and stuff itself
225
- def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys, create_policies: false)
225
+ def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
226
226
  logger.debug("Beetle: creating queue with opts: #{creation_keys.inspect}")
227
227
  queue = bunny.queue(queue_name, creation_keys)
228
- if create_policies
229
- @dead_lettering.bind_dead_letter_queues!(bunny, @client.servers, queue_name, creation_keys)
230
- end
231
228
  logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_keys.inspect}")
232
229
  queue.bind(exchange(exchange_name), binding_keys)
230
+ policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_keys)
231
+ publish_policy_options(policy_options)
233
232
  queue
234
233
  end
235
234
 
@@ -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].queue.subscribe(keys, &callback)
147
+ queues[queue_name].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].queue.subscribed?
153
- queues[queue_name].queue.unsubscribe
152
+ return unless queues[queue_name].subscribed?
153
+ queues[queue_name].unsubscribe
154
154
  end
155
155
 
156
156
  def resume(queue_name)
157
- return if queues[queue_name].queue.subscribed?
157
+ return if queues[queue_name].subscribed?
158
158
  keys, callback = subscriptions[queue_name]
159
- queues[queue_name].queue.subscribe(keys, &callback)
159
+ queues[queue_name].subscribe(keys, &callback)
160
160
  end
161
161
 
162
162
  def create_subscription_callback(queue_name, amqp_queue_name, handler, opts)
@@ -204,12 +204,10 @@ 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, create_policies: false)
207
+ def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
208
208
  queue = channel.queue(queue_name, creation_keys)
209
- target_servers = @client.servers + @client.additional_subscription_servers
210
- if create_policies
211
- @dead_lettering.bind_dead_letter_queues!(channel, target_servers, queue_name, creation_keys)
212
- end
209
+ policy_options = bind_dead_letter_queue!(channel, queue_name, creation_keys)
210
+ publish_policy_options(policy_options)
213
211
  exchange = exchange(exchange_name)
214
212
  queue.bind(exchange, binding_keys)
215
213
  queue
@@ -1,3 +1,3 @@
1
1
  module Beetle
2
- VERSION = "3.0.0.rc1"
2
+ VERSION = "3.0.0.rc2"
3
3
  end
@@ -53,4 +53,54 @@ module Beetle
53
53
  assert_equal "goofy:123", @bs.send(:server_from_settings, {:host => "goofy", :port => 123})
54
54
  end
55
55
  end
56
+
57
+ class BindDeadLetterQueuesTest < Minitest::Test
58
+ def setup
59
+ @queue_name = "QUEUE_NAME"
60
+ @config = Configuration.new
61
+ @client = Client.new @config
62
+ @bs = Base.new(@client)
63
+ @config.logger = Logger.new("/dev/null")
64
+ end
65
+
66
+ test "it does not call out to rabbit if neither dead lettering nor lazy queues are enabled" do
67
+ @client.register_queue(@queue_name, :dead_lettering => false, :lazy => false)
68
+ channel = stub('channel')
69
+ expected_options = {
70
+ :queue_name => "QUEUE_NAME",
71
+ :dead_letter_queue_name=>"QUEUE_NAME_dead_letter",
72
+ :message_ttl => 1000,
73
+ :dead_lettering => false,
74
+ :lazy => false
75
+ }
76
+ assert_equal expected_options, @bs.__send__(:bind_dead_letter_queue!, channel, @queue_name)
77
+ end
78
+
79
+ test "creates and connects the dead letter queue via policies when enabled" do
80
+ @client.register_queue(@queue_name, :dead_lettering => true, :lazy => true)
81
+
82
+ channel = stub('channel')
83
+ channel.expects(:queue).with("#{@queue_name}_dead_letter", {})
84
+
85
+ expected_options = {
86
+ :queue_name => "QUEUE_NAME",
87
+ :dead_letter_queue_name=>"QUEUE_NAME_dead_letter",
88
+ :message_ttl => 1000,
89
+ :dead_lettering => true,
90
+ :lazy => true
91
+ }
92
+ assert_equal expected_options, @bs.__send__(:bind_dead_letter_queue!, channel, @queue_name)
93
+ end
94
+
95
+ test "publish_policy_options declares the beetle policy updates queue and publishes the options" do
96
+ options = { :lazy => true, :dead_lettering => true }
97
+ @bs.logger.stubs(:debug)
98
+ @bs.expects(:queue).with(@client.config.beetle_policy_updates_queue_name)
99
+ exchange = mock("exchange")
100
+ exchange.expects(:publish)
101
+ @bs.expects(:exchange).with(@client.config.beetle_policy_exchange_name).returns(exchange)
102
+ @bs.__send__(:publish_policy_options, options)
103
+ end
104
+
105
+ end
56
106
  end
@@ -15,20 +15,20 @@ module Beetle
15
15
  assert_equal [], @client.additional_subscription_servers
16
16
  end
17
17
 
18
- test "should have no exchanges" do
19
- assert @client.exchanges.empty?
18
+ test "should have only the system exchange" do
19
+ assert_equal ["beetle-policies"], @client.exchanges.keys
20
20
  end
21
21
 
22
- test "should have no queues" do
23
- assert @client.queues.empty?
22
+ test "should have only the beetle policy queue" do
23
+ assert_equal ["beetle-policy-updates"], @client.queues.keys
24
24
  end
25
25
 
26
26
  test "should have no messages" do
27
- assert @client.messages.empty?
27
+ assert_equal [], @client.messages.keys
28
28
  end
29
29
 
30
- test "should have no bindings" do
31
- assert @client.bindings.empty?
30
+ test "should have only one binding for the beetle policy updates" do
31
+ assert_equal ["beetle-policy-updates"], @client.bindings.keys
32
32
  end
33
33
  end
34
34
 
@@ -308,13 +308,6 @@ 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
-
318
311
  test "should delegate rpc calls to the publisher instance" do
319
312
  client = Client.new
320
313
  client.register_message("deadletter")
@@ -363,6 +356,12 @@ module Beetle
363
356
  client.stop_listening
364
357
  end
365
358
 
359
+ test "should delegate set_queue_policies! to the dead lettering instance" do
360
+ client = Client.new
361
+ client.instance_variable_get(:@dead_lettering).expects(:set_queue_policies!)
362
+ client.set_queue_policies!({})
363
+ end
364
+
366
365
  test "should delegate pause_listening to the subscriber instance" do
367
366
  client = Client.new
368
367
  client.register_queue(:test)
@@ -1,34 +1,13 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  module Beetle
4
- class SetDeadLetteringsTest < Minitest::Test
5
- def setup
6
- @config = Configuration.new
7
- @client = Client.new @config
8
- @dead_lettering = DeadLettering.new(@client)
9
- @config.dead_lettering_enabled = true
10
- end
11
-
12
- test "creates a dead letter queue for each server" do
13
- servers = %w(a b)
14
-
15
- @dead_lettering.expects(:set_queue_policy!).
16
- with("a", "QUEUE_NAME", :message_ttl => 10000)
17
- @dead_lettering.expects(:set_queue_policy!).
18
- with("b", "QUEUE_NAME", :message_ttl => 10000)
19
-
20
- @dead_lettering.set_queue_policies!(servers, "QUEUE_NAME", :message_ttl => 10000)
21
- end
22
- end
23
-
24
4
  class SetDeadLetterPolicyTest < Minitest::Test
25
5
  def setup
26
6
  @server = "localhost:15672"
27
7
  @queue_name = "QUEUE_NAME"
28
8
  @config = Configuration.new
29
- @client = Client.new @config
30
9
  @config.logger = Logger.new("/dev/null")
31
- @dead_lettering = DeadLettering.new(@client)
10
+ @dead_lettering = DeadLettering.new(@config)
32
11
  end
33
12
 
34
13
  test "raises exception when queue name wasn't specified" do
@@ -43,6 +22,22 @@ module Beetle
43
22
  end
44
23
  end
45
24
 
25
+ test "set_queue_policies! calls set_queue_policy for both target queue and dead letter queue" do
26
+ options = {
27
+ :server => "server", :lazy => true, :dead_lettering => true,
28
+ :queue_name => "QUEUE_NAME", :dead_letter_queue_name => "QUEUE_NAME_dead_letter",
29
+ :message_ttl => 10000
30
+ }
31
+ @dead_lettering.expects(:set_queue_policy!).with("server", "QUEUE_NAME",
32
+ :lazy => true, :dead_lettering => true,
33
+ :routing_key => "QUEUE_NAME_dead_letter")
34
+ @dead_lettering.expects(:set_queue_policy!).with("server", "QUEUE_NAME_dead_letter",
35
+ :lazy => true, :dead_lettering => true,
36
+ :routing_key => "QUEUE_NAME",
37
+ :message_ttl => 10000)
38
+ @dead_lettering.set_queue_policies!(options)
39
+ end
40
+
46
41
  test "creates a policy by posting to the rabbitmq if dead lettering is enabled" do
47
42
  stub_request(:put, "http://localhost:15672/api/policies/%2F/QUEUE_NAME_policy")
48
43
  .with(basic_auth: ['guest', 'guest'])
@@ -56,7 +51,7 @@ module Beetle
56
51
  }}.to_json)
57
52
  .to_return(:status => 204)
58
53
 
59
- @dead_lettering.set_queue_policy!(@server, @queue_name, :lazy => false, :dead_lettering => true)
54
+ @dead_lettering.set_queue_policy!(@server, @queue_name, :lazy => false, :dead_lettering => true, :routing_key => "QUEUE_NAME_dead_letter")
60
55
  end
61
56
 
62
57
  test "creates a policy by posting to the rabbitmq if lazy queues are enabled" do
@@ -98,7 +93,7 @@ module Beetle
98
93
  }}.to_json)
99
94
  .to_return(:status => 204)
100
95
 
101
- @dead_lettering.set_queue_policy!(@server, @queue_name, :dead_lettering => true, :message_ttl => 10000)
96
+ @dead_lettering.set_queue_policy!(@server, @queue_name, :dead_lettering => true, :message_ttl => 10000, :routing_key => "QUEUE_NAME_dead_letter")
102
97
  end
103
98
 
104
99
  test "properly encodes the vhost from the configuration" do
@@ -116,42 +111,7 @@ module Beetle
116
111
 
117
112
  @config.vhost = "foo/"
118
113
 
119
- @dead_lettering.set_queue_policy!(@server, @queue_name, :dead_lettering => true)
120
- end
121
- end
122
-
123
- class BindDeadLetterQueuesTest < Minitest::Test
124
- def setup
125
- @queue_name = "QUEUE_NAME"
126
- @config = Configuration.new
127
- @client = Client.new @config
128
- @config.logger = Logger.new("/dev/null")
129
- @dead_lettering = DeadLettering.new(@client)
130
- @servers = ["localhost:55672"]
131
- end
132
-
133
- test "is does not call out to rabbit if neither dead lettering nor lazy queues are enabled" do
134
- @client.register_queue(@queue_name, :dead_lettering => false, :lazy => false)
135
- channel = stub('channel')
136
- @dead_lettering.expects(:run_rabbit_http_request).never
137
- @dead_lettering.bind_dead_letter_queues!(channel, @servers, @queue_name)
138
- end
139
-
140
- test "creates and connects the dead letter queue via policies when enabled" do
141
- @client.register_queue(@queue_name, :dead_lettering => true, :lazy => false)
142
-
143
- channel = stub('channel')
144
-
145
- channel.expects(:queue).with("#{@queue_name}_dead_letter", {})
146
- @dead_lettering.expects(:set_queue_policies!).with(@servers, @queue_name, :dead_lettering => true, :lazy => false)
147
- @dead_lettering.expects(:set_queue_policies!).with(@servers, "#{@queue_name}_dead_letter",
148
- :routing_key => @queue_name,
149
- :message_ttl => 1000,
150
- :dead_lettering => true,
151
- :lazy => false
152
- )
153
-
154
- @dead_lettering.bind_dead_letter_queues!(channel, @servers, @queue_name)
114
+ @dead_lettering.set_queue_policy!(@server, @queue_name, :dead_lettering => true, :routing_key => "QUEUE_NAME_dead_letter")
155
115
  end
156
116
  end
157
117
  end
@@ -263,7 +263,8 @@ module Beetle
263
263
 
264
264
  class PublisherQueueManagementTest < Minitest::Test
265
265
  def setup
266
- @client = Client.new
266
+ @config = Configuration.new
267
+ @client = Client.new(@config)
267
268
  @pub = Publisher.new(@client)
268
269
  end
269
270
 
@@ -275,48 +276,15 @@ module Beetle
275
276
  test "binding a queue should create it using the config and bind it to the exchange with the name specified" do
276
277
  @client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#", :arguments => {"foo" => "fighter"})
277
278
  @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
289
- @client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#", :arguments => {"foo" => "fighter"})
290
- @pub.expects(:exchange).with("some_exchange").returns(:the_exchange)
279
+ @pub.expects(:publish_policy_options)
291
280
  q = mock("queue")
292
281
  q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
293
282
  m = mock("Bunny")
294
283
  m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"foo" => "fighter"}).returns(q)
295
284
  @pub.expects(:bunny).returns(m).twice
296
285
 
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
-
310
286
  @pub.send(:queue, "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"]
287
+ assert_equal q, @pub.send(:queues)["some_queue"]
320
288
  end
321
289
 
322
290
  test "should bind the defined queues for the used exchanges when publishing" do
@@ -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" => Base::QueueInfo.new(q,false)})
92
+ @sub.stubs(:queues).returns("a" => q)
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" => Base::QueueInfo.new(q,false)})
100
+ @sub.stubs(:queues).returns("a" => q)
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" => Base::QueueInfo.new(q,false)})
108
+ @sub.stubs(:queues).returns("a" => q)
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" => Base::QueueInfo.new(q,false)})
116
+ @sub.stubs(:queues).returns("a" => q)
117
117
  @sub.__send__(:resume, "a")
118
118
  end
119
119
 
@@ -146,27 +146,17 @@ module Beetle
146
146
  test "binding a queue should create it using the config and bind it to the exchange with the name specified" do
147
147
  @client.register_queue("some_queue", "durable" => true, "exchange" => "some_exchange", "key" => "haha.#", "arguments" => {"schmu" => 5})
148
148
  @sub.expects(:exchange).with("some_exchange").returns(:the_exchange)
149
+ @sub.expects(:publish_policy_options)
149
150
  q = mock("queue")
150
151
  q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
151
- m = mock("MQ")
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)
152
+ channel = mock("MQ")
153
+ creation_opts = {:durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"schmu" => 5}}
154
+ channel.expects(:queue).with("some_queue", creation_opts).returns(q)
155
+ @sub.expects(:channel).returns(channel).twice
156
+ @sub.expects(:bind_dead_letter_queue!).with(channel, "some_queue", creation_opts)
154
157
 
155
158
  @sub.send(:queue, "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
159
+ assert_equal q, @sub.send(:queues)["some_queue"]
170
160
  end
171
161
 
172
162
  test "binding queues should bind all queues" do
@@ -370,7 +360,7 @@ module Beetle
370
360
  q = mock("QUEUE")
371
361
  subscription_options = {:ack => true, :key => "#"}
372
362
  q.expects(:subscribe).with(subscription_options).yields(header, "foo")
373
- @sub.expects(:queues).returns({"some_queue" => Base::QueueInfo.new(q,false)}).once
363
+ @sub.expects(:queues).returns("some_queue" => q).once
374
364
  @sub.send(:subscribe, "some_queue")
375
365
  assert block_called
376
366
  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: 3.0.0.rc1
4
+ version: 3.0.0.rc2
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-04-26 00:00:00.000000000 Z
15
+ date: 2019-05-13 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: bunny