beetle 3.4.2 → 3.5.3

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: '08db25367467939ff6a625b0caf2b940832b398c7988189ac2a0e91d5244a78b'
4
- data.tar.gz: d9ffc4a722b0d86db98e81e0f9080b76e2fbd01537cbb4a6839b00665e778f19
3
+ metadata.gz: bce54bf1dc2290bb4c1598f6210b1c292d09691e91df2f67e913747535c90f2d
4
+ data.tar.gz: e6f510fb5b78a7ed0483f713920222ff1959e7a3e3073aac61abed25af56b0bd
5
5
  SHA512:
6
- metadata.gz: c7f986880a871a59a74ee9e3fc63b9b384097713eedc9f106c7b799cd6b8762714d05d181665ac5aadea0675fd10f30acfbaec8fcdf921a31721c609220b95ad
7
- data.tar.gz: 3beb91290f71cf8191f9abe0a116732e0e880a3e0e57d2c774c2c417bde4fb697b7980e2d2f6af0bdfcd601b124c7c4286a796fada014771be3bb8b049130d12
6
+ metadata.gz: 8682a1720108f7e95ad9802bcfe5b30283c735cfaa67323e5aca6bca1e1c06d0b6bb58d8fd2b8f4fc1fb7032579832667b78bab0c0f7013a937556650ad14ad7
7
+ data.tar.gz: 255b3fd3827a1f33c1c244967649ab8eaa1adc8f6daa3a111b21e299f1bcc0341f324a1bee3f2c578f5c93b39eeb913caf2c3a6d8ea88d1e89c028c48576e1b0
data/Rakefile CHANGED
@@ -115,18 +115,14 @@ Rake::TestTask.new do |t|
115
115
  t.warning = false
116
116
  end
117
117
 
118
- require 'rdoc/task'
119
-
120
- RDoc::Task.new do |rdoc|
121
- rdoc.rdoc_dir = 'site/rdoc'
122
- rdoc.title = 'Beetle'
123
- rdoc.main = 'README.rdoc'
124
- rdoc.options << '--line-numbers' << '--inline-source' << '--quiet'
125
- rdoc.rdoc_files.include('**/*.rdoc')
126
- rdoc.rdoc_files.include('MIT-LICENSE')
127
- rdoc.rdoc_files.include('lib/**/*.rb')
118
+ task :clean do
119
+ sh "rm -f tmp/*.output tmp/*.log tmp/master-dir/* tmp/slave-dir/* tmp/*lock tmp/*pid test.log" unless ENV['GITHUB_ACTIONS']
128
120
  end
129
121
 
130
- task :clean do
131
- sh "rm -f tmp/*.output tmp/*.log tmp/master-dir/* tmp/slave-dir/* tmp/*lock tmp/*pid test.log"
122
+ require 'yard'
123
+
124
+ YARD::Rake::YardocTask.new do |t|
125
+ OTHER_PATHS = %w()
126
+ t.files = ['lib/**/*.rb'] + OTHER_PATHS
127
+ t.options = %w(--markup-provider=redcarpet --markup=markdown --main=README.md --output-dir=site/yard)
132
128
  end
data/beetle.gemspec CHANGED
@@ -39,8 +39,10 @@ Gem::Specification.new do |s|
39
39
  s.add_development_dependency "mocha", "~> 1.3.0"
40
40
  s.add_development_dependency "mysql2", "~> 0.4.4"
41
41
  s.add_development_dependency "rake", "~> 13.0"
42
- s.add_development_dependency "rdoc", "~> 4.0"
43
42
  s.add_development_dependency "simplecov", "~> 0.15"
44
43
  s.add_development_dependency "webmock", "~> 3.0"
45
44
  s.add_development_dependency "websocket-eventmachine-client"
45
+ s.add_development_dependency 'yard'
46
+ s.add_development_dependency 'redcarpet'
47
+ s.add_development_dependency 'github-markup'
46
48
  end
@@ -17,7 +17,7 @@ Beetle.config.logger.level = Logger::INFO
17
17
  client = Beetle::Client.new
18
18
 
19
19
  # use two servers
20
- Beetle.config.servers = "localhost:5672, localhost:5673"
20
+ Beetle.config.servers = ENV["RABBITMQ_SERVERS"] || "localhost:5672, localhost:5673"
21
21
  # instantiate a client
22
22
  client = Beetle::Client.new
23
23
 
data/examples/rpc.rb CHANGED
@@ -4,7 +4,7 @@ require File.expand_path(File.dirname(__FILE__)+"/../lib/beetle")
4
4
 
5
5
  # suppress debug messages
6
6
  Beetle.config.logger.level = Logger::INFO
7
- Beetle.config.servers = "localhost:5672, localhost:5673"
7
+ Beetle.config.servers = ENV["RABBITMQ_SERVERS"] || "localhost:5672, localhost:5673"
8
8
  # instantiate a client
9
9
 
10
10
  client = Beetle::Client.new
@@ -24,6 +24,26 @@ Feature: Redis auto failover
24
24
  Given a redis server "redis-1" exists as master
25
25
  Then the role of redis server "redis-1" should be "slave"
26
26
 
27
+ Scenario: Successful redis master switch with multiple slaves
28
+ And a redis server "redis-3" exists as slave of "redis-3"
29
+ Given a redis configuration server using redis servers "redis-1,redis-2,redis-3" with clients "rc-client-1,rc-client-2" exists
30
+ And a redis configuration client "rc-client-1" using redis servers "redis-1,redis-2,redis-3" exists
31
+ And a redis configuration client "rc-client-2" using redis servers "redis-1,redis-2,redis-3" exists
32
+ And a beetle handler using the redis-master file from "rc-client-1" exists
33
+ And redis server "redis-1" is down
34
+ And the retry timeout for the redis master check is reached
35
+ Then a system notification for "redis-1" not being available should be sent
36
+ And the role of redis server "redis-2" should be "master"
37
+ And the redis master file of the redis configuration server should contain "redis-2"
38
+ And the redis master of "rc-client-1" should be "redis-2"
39
+ And the redis master of "rc-client-2" should be "redis-2"
40
+ And the redis master of the beetle handler should be "redis-2"
41
+ And a system notification for switching from "redis-1" to "redis-2" should be sent
42
+ Given a redis server "redis-1" exists as master
43
+ Then the role of redis server "redis-1" should be "slave"
44
+ And the redis server "redis-1" is a slave of "redis-2"
45
+ And the redis server "redis-3" is a slave of "redis-2"
46
+
27
47
  Scenario: Successful single redis master switch with multiple failover sets
28
48
  Given a redis server "redis-3" exists as master
29
49
  And a redis server "redis-4" exists as slave of "redis-3"
@@ -1,8 +1,9 @@
1
1
  Given /^consul state has been cleared$/ do
2
+ consul_host = ENV["CONSUL_HOST"] || "localhost:8500"
2
3
  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"
4
+ system "curl --silent --request PUT http://#{consul_host}/v1/kv/apps/beetle/config/ >/dev/null"
5
+ system "curl --silent --request PUT http://#{consul_host}/v1/kv/shared/config/ >/dev/null"
6
+ system "curl --silent --request DELETE http://#{consul_host}/v1/kv/apps/beetle/state/redis_master_file_content >/dev/null"
6
7
  end
7
8
 
8
9
  Given /^a redis server "([^\"]*)" exists as master$/ do |redis_name|
@@ -93,7 +94,6 @@ Given /^an old redis master file for "([^\"]*)" with master "([^\"]*)" exists$/
93
94
  end
94
95
  end
95
96
 
96
-
97
97
  Then /^the role of redis server "([^\"]*)" should be "(master|slave)"$/ do |redis_name, role|
98
98
  expected_role = false
99
99
  10.times do
@@ -103,6 +103,16 @@ Then /^the role of redis server "([^\"]*)" should be "(master|slave)"$/ do |redi
103
103
  assert expected_role, "#{redis_name} is not a #{role}"
104
104
  end
105
105
 
106
+ Then /^the redis server "([^\"]*)" is a slave of "([^\"]*)"$/ do |redis_name, redis_master_name|
107
+ master = TestDaemons::Redis[redis_master_name].redis
108
+ slave = TestDaemons::Redis[redis_name].redis
109
+ 3.times do
110
+ sleep 1
111
+ break if slave.slave_of?(master.host, master.port)
112
+ end
113
+ assert slave.slave_of?(master.host, master.port)
114
+ end
115
+
106
116
  Then /^the redis master of "([^\"]*)" (?:in system "([^"]*)" )?should be "([^\"]*)"$/ do |redis_configuration_client_name, system_name, redis_name|
107
117
  system_name ||= "system"
108
118
  master_file = redis_master_file(redis_configuration_client_name)
@@ -143,11 +153,21 @@ end
143
153
  Then /^the redis master of the beetle handler should be "([^\"]*)"$/ do |redis_name|
144
154
  Beetle.config.servers = "127.0.0.1:5672" # rabbitmq
145
155
  Beetle.config.logger.level = Logger::INFO
146
- client = Beetle::Client.new.configure :auto_delete => true do |config|
147
- config.queue(:echo, :lazy => true, :dead_lettering => true)
148
- config.message(:echo)
156
+ redis_master = TestDaemons::Redis[redis_name].ip_with_port
157
+ response = nil
158
+ expected_response = ['OK', redis_master]
159
+ 3.times do |i|
160
+ client = Beetle::Client.new.configure :auto_delete => true do |config|
161
+ config.queue(:echo, :lazy => true, :dead_lettering => true)
162
+ config.message(:echo)
163
+ end
164
+ t1 = Time.now
165
+ response = client.rpc(:echo, 'echo')
166
+ t2 = Time.now
167
+ # puts "OK,#{redis_master} =?= #{response.join(',')} after #{t2-t1}, attempt #{i+1}"
168
+ break if expected_response == response
149
169
  end
150
- assert_match /#{TestDaemons::Redis[redis_name].ip_with_port}/, client.rpc(:echo, 'nil').second
170
+ assert_equal expected_response, response
151
171
  end
152
172
 
153
173
  Then /^a system notification for "([^\"]*)" not being available should be sent$/ do |redis_name|
@@ -25,9 +25,10 @@ module TestDaemons
25
25
 
26
26
  def self.daemon_controller
27
27
  clients_parameter_string = @@redis_configuration_clients.blank? ? "" : "--client-ids #{@@redis_configuration_clients}"
28
+ consul_host = ENV["CONSUL_HOST"] || "localhost:8500"
28
29
  DaemonController.new(
29
30
  :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} --consul http://localhost:8500",
31
+ :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://#{consul_host}",
31
32
  :ping_command => lambda{ answers_text_requests? },
32
33
  :pid_file => pid_file,
33
34
  :log_file => log_file,
data/lib/beetle/base.rb CHANGED
@@ -67,23 +67,25 @@ module Beetle
67
67
  logger.debug("Beetle: binding queue #{name} with internal name #{opts[:amqp_name]} on server #{@server}")
68
68
  queue_name = opts[:amqp_name]
69
69
  creation_options = opts.slice(*QUEUE_CREATION_KEYS)
70
- the_queue = nil
70
+
71
+ the_queue = declare_queue!(queue_name, creation_options)
71
72
  @client.bindings[name].each do |binding_options|
72
73
  exchange_name = binding_options[:exchange]
73
74
  binding_options = binding_options.slice(*QUEUE_BINDING_KEYS)
74
- the_queue = bind_queue!(queue_name, creation_options, exchange_name, binding_options)
75
+ logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_options.inspect}")
76
+ bind_queue!(the_queue, exchange_name, binding_options)
75
77
  end
76
78
  the_queue
77
79
  end
78
80
  end
79
81
 
80
- def bind_dead_letter_queue!(channel, target_queue, creation_keys = {})
82
+ def bind_dead_letter_queue!(channel, target_queue, creation_options = {})
81
83
  policy_options = @client.queues[target_queue].slice(:dead_lettering, :lazy, :dead_lettering_msg_ttl)
82
84
  policy_options[:message_ttl] = policy_options.delete(:dead_lettering_msg_ttl)
83
85
  dead_letter_queue_name = "#{target_queue}_dead_letter"
84
86
  if policy_options[:dead_lettering]
85
- logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_keys.inspect}")
86
- channel.queue(dead_letter_queue_name, creation_keys)
87
+ logger.debug("Beetle: creating dead letter queue #{dead_letter_queue_name} with opts: #{creation_options.inspect}")
88
+ channel.queue(dead_letter_queue_name, creation_options)
87
89
  end
88
90
  return {
89
91
  :queue_name => target_queue,
@@ -93,7 +95,7 @@ module Beetle
93
95
  }.merge(policy_options)
94
96
  end
95
97
 
96
- # called by <tt>bind_queue!</tt>
98
+ # called by <tt>declare_queue!</tt>
97
99
  def publish_policy_options(options)
98
100
  # avoid endless recursion
99
101
  return if options[:queue_name] == @client.config.beetle_policy_updates_queue_name
data/lib/beetle/client.rb CHANGED
@@ -280,6 +280,13 @@ module Beetle
280
280
  publisher.throttled?
281
281
  end
282
282
 
283
+ # set up queues and policies for all configured queues. Otherwise this will
284
+ # happen on first use of an exchange, which can be undesired for latency
285
+ # sensitive endpoints. Only needs to be called once.
286
+ def setup_queues_and_policies
287
+ publisher.setup_queues_and_policies
288
+ end
289
+
283
290
  # traces queues without consuming them. useful for debugging message flow.
284
291
  def trace(queue_names=self.queues.keys, tracer=nil, &block)
285
292
  queues_to_trace = self.queues.slice(*queue_names)
@@ -378,8 +385,12 @@ module Beetle
378
385
  end
379
386
 
380
387
  def load_brokers_from_config
381
- @servers = config.servers.split(/ *, */)
382
- @additional_subscription_servers = config.additional_subscription_servers.split(/ *, */)
388
+ @servers = parse_server_list(config.servers)
389
+ @additional_subscription_servers = parse_server_list(config.additional_subscription_servers) - @servers
390
+ end
391
+
392
+ def parse_server_list(s)
393
+ s.split(/ *, */).uniq.reject(&:blank?)
383
394
  end
384
395
  end
385
396
  end
@@ -34,7 +34,7 @@ module Beetle
34
34
  Bunny::ConnectionError, Bunny::ForcedChannelCloseError, Bunny::ForcedConnectionCloseError,
35
35
  Bunny::MessageError, Bunny::ProtocolError, Bunny::ServerDownError, Bunny::UnsubscribeError,
36
36
  Bunny::AcknowledgementError, Qrack::BufferOverflowError, Qrack::InvalidTypeError,
37
- Errno::EHOSTUNREACH, Errno::ECONNRESET, Timeout::Error
37
+ Errno::EHOSTUNREACH, Errno::ECONNRESET, Errno::ETIMEDOUT, Timeout::Error
38
38
  ]
39
39
  end
40
40
 
@@ -66,6 +66,7 @@ module Beetle
66
66
  logger.debug "Beetle: message sent!"
67
67
  published = 1
68
68
  rescue *bunny_exceptions => e
69
+ logger.warn("Beetle: publishing exception #{e} #{e.backtrace[0..4].join("\n")}")
69
70
  stop!(e)
70
71
  tries -= 1
71
72
  # retry same server on receiving the first exception for it (might have been a normal restart)
@@ -98,6 +99,7 @@ module Beetle
98
99
  published << @server
99
100
  logger.debug "Beetle: message sent (#{published})!"
100
101
  rescue *bunny_exceptions => e
102
+ logger.warn("Beetle: publishing exception #{e} #{e.backtrace[0..4].join("\n")}")
101
103
  stop!(e)
102
104
  retry if (tries += 1) == 1
103
105
  mark_server_dead
@@ -169,10 +171,14 @@ module Beetle
169
171
  end
170
172
  end
171
173
 
172
- def setup_queues_and_policies(queue_names) #:nodoc:
174
+ def setup_queues_and_policies
173
175
  each_server do
174
- queue_names.each do |name|
175
- queue(name, create_policies: true)
176
+ begin
177
+ @client.queues.keys.each do |name|
178
+ queue(name)
179
+ end
180
+ rescue => e
181
+ logger.warn "Beetle: failed setting up queues and policies on #{@server}: #{e}"
176
182
  end
177
183
  end
178
184
  end
@@ -247,17 +253,19 @@ module Beetle
247
253
  @exchanges_with_bound_queues[exchange_name] = true
248
254
  end
249
255
 
250
- # TODO: Refactor, fetch the keys and stuff itself
251
- def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
252
- logger.debug("Beetle: creating queue with opts: #{creation_keys.inspect}")
253
- queue = bunny.queue(queue_name, creation_keys)
254
- logger.debug("Beetle: binding queue #{queue_name} to #{exchange_name} with opts: #{binding_keys.inspect}")
255
- queue.bind(exchange(exchange_name), binding_keys)
256
- policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_keys)
256
+ def declare_queue!(queue_name, creation_options)
257
+ logger.debug("Beetle: creating queue with opts: #{creation_options.inspect}")
258
+ queue = bunny.queue(queue_name, creation_options)
259
+
260
+ policy_options = bind_dead_letter_queue!(bunny, queue_name, creation_options)
257
261
  publish_policy_options(policy_options)
258
262
  queue
259
263
  end
260
264
 
265
+ def bind_queue!(queue, exchange_name, binding_options)
266
+ queue.bind(exchange(exchange_name), binding_options)
267
+ end
268
+
261
269
  def stop!(exception=nil)
262
270
  return unless bunny?
263
271
  timeout = @client.config.publishing_timeout + @client.config.publisher_connect_timeout + 1
@@ -214,18 +214,20 @@ module Beetle
214
214
  channel.__send__(opts[:type], name, opts.slice(*EXCHANGE_CREATION_KEYS))
215
215
  end
216
216
 
217
- def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
218
- queue = channel.queue(queue_name, creation_keys)
217
+ def declare_queue!(queue_name, creation_options)
218
+ queue = channel.queue(queue_name, creation_options)
219
219
  unless tracing?
220
220
  # we don't want to create dead-letter queues for tracing
221
- policy_options = bind_dead_letter_queue!(channel, queue_name, creation_keys)
221
+ policy_options = bind_dead_letter_queue!(channel, queue_name, creation_options)
222
222
  publish_policy_options(policy_options)
223
223
  end
224
- exchange = exchange(exchange_name)
225
- queue.bind(exchange, binding_keys)
226
224
  queue
227
225
  end
228
226
 
227
+ def bind_queue!(queue, exchange_name, binding_options)
228
+ queue.bind(exchange(exchange_name), binding_options)
229
+ end
230
+
229
231
  def connection_settings
230
232
  {
231
233
  :host => current_host, :port => current_port, :logging => false,
@@ -1,3 +1,3 @@
1
1
  module Beetle
2
- VERSION = "3.4.2"
2
+ VERSION = "3.5.3"
3
3
  end
@@ -7,7 +7,7 @@ class AMQPGemBehaviorTest < Minitest::Test
7
7
  begin
8
8
  exception = nil
9
9
  EM.run do
10
- AMQP.start(:logging => false) do |connection|
10
+ AMQP.start(logging: false, host: ENV['RABBITMQ_SERVERS'] || 'localhost') do |connection|
11
11
  EM::Timer.new(1){ connection.close { EM.stop }}
12
12
  channel = AMQP::Channel.new(connection)
13
13
  channel.on_error { puts "woot"}
@@ -26,7 +26,7 @@ module Beetle
26
26
  end
27
27
 
28
28
  test "server should be initialized" do
29
- assert_equal @bs.servers.first, @bs.server
29
+ assert @bs.server
30
30
  end
31
31
 
32
32
  test "current_host should return the hostname of the current server" do
@@ -8,7 +8,7 @@ module Beetle
8
8
  end
9
9
 
10
10
  test "should have a default server" do
11
- assert_equal ["localhost:5672"], @client.servers
11
+ assert !@client.servers.empty?
12
12
  end
13
13
 
14
14
  test "should have no additional subscription servers" do
@@ -282,6 +282,12 @@ module Beetle
282
282
  client.stop_publishing
283
283
  end
284
284
 
285
+ test "should delegate setup_queues_and_policies to the publisher instance" do
286
+ client = Client.new
287
+ client.send(:publisher).expects(:setup_queues_and_policies)
288
+ client.setup_queues_and_policies
289
+ end
290
+
285
291
  test "should delegate queue purging to the publisher instance" do
286
292
  client = Client.new
287
293
  client.register_queue(:queue)
@@ -337,17 +343,17 @@ module Beetle
337
343
 
338
344
  test "trying to listen to an unknown queue should raise an exception" do
339
345
  client = Client.new
340
- assert_raises(UnknownQueue) { Client.new.listen_queues([:foobar])}
346
+ assert_raises(UnknownQueue) { client.listen_queues([:foobar])}
341
347
  end
342
348
 
343
349
  test "trying to pause listening on an unknown queue should raise an exception" do
344
350
  client = Client.new
345
- assert_raises(UnknownQueue) { Client.new.pause_listening(:foobar)}
351
+ assert_raises(UnknownQueue) { client.pause_listening(:foobar)}
346
352
  end
347
353
 
348
354
  test "trying to resume listening on an unknown queue should raise an exception" do
349
355
  client = Client.new
350
- assert_raises(UnknownQueue) { Client.new.pause_listening(:foobar)}
356
+ assert_raises(UnknownQueue) { client.pause_listening(:foobar)}
351
357
  end
352
358
 
353
359
  test "should delegate stop_listening to the subscriber instance" do
@@ -451,4 +457,39 @@ module Beetle
451
457
  msg_stub
452
458
  end
453
459
  end
460
+
461
+ class ServerDeduplicationTest < Minitest::Test
462
+ def setup
463
+ @config = Configuration.new
464
+ @config.servers = "localhost:5672,localhost:5672"
465
+ @config.additional_subscription_servers = @config.servers + ",localhost:1234,localhost:1234"
466
+ @client = Client.new(@config)
467
+ end
468
+
469
+ test "duplicates are removed from the server list" do
470
+ assert_equal ["localhost:5672"], @client.servers
471
+ end
472
+
473
+ test "duplicates and servers in the server list are removed from the additional subscription server list" do
474
+ assert_equal ["localhost:1234"], @client.additional_subscription_servers
475
+ end
476
+ end
477
+
478
+ class EmptyServerStringTest < Minitest::Test
479
+ def setup
480
+ @config = Configuration.new
481
+ @config.servers = "localhost:5672,\t,localhost:5672, "
482
+ @config.additional_subscription_servers = @config.servers + ",localhost:1234, , ,,"
483
+ @client = Client.new(@config)
484
+ end
485
+
486
+ test "empty strings are removed from the server list" do
487
+ assert_equal ["localhost:5672"], @client.servers
488
+ end
489
+
490
+ test "empty strings are removed from the additional subscription server list" do
491
+ assert_equal ["localhost:1234"], @client.additional_subscription_servers
492
+ end
493
+ end
494
+
454
495
  end
@@ -87,7 +87,7 @@ module Beetle
87
87
  private
88
88
  def redis_test_master_file(server_string)
89
89
  tmp_dir = File.expand_path("../../../tmp", __FILE__)
90
- Dir.mkdir(tmp_dir) unless File.exists?(tmp_dir)
90
+ Dir.mkdir(tmp_dir) unless File.exist?(tmp_dir)
91
91
  path = tmp_dir + "/redis-master-for-unit-tests"
92
92
  File.open(path, "w"){|f| f.puts server_string}
93
93
  path
@@ -77,7 +77,9 @@ module Beetle
77
77
 
78
78
  class PublisherPublishingTest < Minitest::Test
79
79
  def setup
80
- @client = Client.new
80
+ @config = Configuration.new
81
+ @config.servers = ENV['RABBITMQ_SERVERS'].split(',').first if ENV['RABBITMQ_SERVERS']
82
+ @client = Client.new(@config)
81
83
  @pub = Publisher.new(@client)
82
84
  @pub.stubs(:bind_queues_for_exchange)
83
85
  @client.register_queue("mama", :exchange => "mama-exchange")
@@ -277,6 +279,7 @@ module Beetle
277
279
  class PublisherQueueManagementTest < Minitest::Test
278
280
  def setup
279
281
  @config = Configuration.new
282
+ @config.servers = ENV['RABBITMQ_SERVERS'] if ENV['RABBITMQ_SERVERS']
280
283
  @client = Client.new(@config)
281
284
  @pub = Publisher.new(@client)
282
285
  end
@@ -304,7 +307,11 @@ module Beetle
304
307
  @client.register_queue('test_queue_1', :exchange => 'test_exchange')
305
308
  @client.register_queue('test_queue_2', :exchange => 'test_exchange')
306
309
  @client.register_queue('test_queue_3', :exchange => 'test_exchange_2')
307
- @pub.expects(:bind_queue!).returns(1).times(3)
310
+ queue = mock("queue")
311
+ @pub.expects(:bind_queue!).with(queue, "test_exchange", {:key => "test_queue_1"}).once
312
+ @pub.expects(:bind_queue!).with(queue, "test_exchange", {:key => "test_queue_2"}).once
313
+ @pub.expects(:bind_queue!).with(queue, "test_exchange_2", {:key => "test_queue_3"}).once
314
+ @pub.expects(:declare_queue!).returns(queue).times(3)
308
315
  @pub.send(:bind_queues_for_exchange, 'test_exchange')
309
316
  @pub.send(:bind_queues_for_exchange, 'test_exchange_2')
310
317
  end
@@ -312,8 +319,22 @@ module Beetle
312
319
  test "should not rebind the defined queues for the used exchanges if they already have been bound" do
313
320
  @client.register_queue('test_queue_1', :exchange => 'test_exchange')
314
321
  @client.register_queue('test_queue_2', :exchange => 'test_exchange')
315
- @pub.expects(:bind_queue!).twice
322
+ queue = mock("queue")
323
+ @pub.expects(:declare_queue!).returns(queue).twice
324
+ @pub.expects(:bind_queue!).with(queue, "test_exchange", {:key => "test_queue_1"}).once
325
+ @pub.expects(:bind_queue!).with(queue, "test_exchange", {:key => "test_queue_2"}).once
326
+ @pub.send(:bind_queues_for_exchange, 'test_exchange')
316
327
  @pub.send(:bind_queues_for_exchange, 'test_exchange')
328
+ end
329
+
330
+ test "should declare queues only once even with many bindings" do
331
+
332
+ @client.register_queue('test_queue', :exchange => 'test_exchange')
333
+ @client.register_binding('test_queue', :exchange => 'test_exchange', :key => 'sir-message-a-lot')
334
+ queue = mock("queue")
335
+ @pub.expects(:declare_queue!).returns(queue).once
336
+ @pub.expects(:bind_queue!).with(queue, "test_exchange", {:key => "test_queue"}).once
337
+ @pub.expects(:bind_queue!).with(queue, "test_exchange", {:key => "sir-message-a-lot"}).once
317
338
  @pub.send(:bind_queues_for_exchange, 'test_exchange')
318
339
  end
319
340
 
@@ -342,14 +363,34 @@ module Beetle
342
363
  end
343
364
 
344
365
  test "setting up queues and policies should iterate over all servers" do
345
- @pub.servers = %w(a b)
346
- queue = mock("queue")
366
+ client = Client.new
367
+ client.register_queue("queue")
368
+ pub = Publisher.new(client)
369
+ pub.servers = %w(a b)
370
+
347
371
  s = sequence("setup")
348
- @pub.expects(:set_current_server).with("a").in_sequence(s)
349
- @pub.expects(:queue).with("queue", :create_policies => true).returns(queue).in_sequence(s)
350
- @pub.expects(:set_current_server).with("b").in_sequence(s)
351
- @pub.expects(:queue).with("queue", :create_policies => true).returns(queue).in_sequence(s)
352
- @pub.setup_queues_and_policies(["queue"])
372
+ pub.expects(:set_current_server).with("a").in_sequence(s)
373
+ pub.expects(:queue).with(client.config.beetle_policy_updates_queue_name).in_sequence(s)
374
+ pub.expects(:queue).with("queue").in_sequence(s)
375
+ pub.expects(:set_current_server).with("b").in_sequence(s)
376
+ pub.expects(:queue).with(client.config.beetle_policy_updates_queue_name).in_sequence(s)
377
+ pub.expects(:queue).with("queue").in_sequence(s)
378
+
379
+ pub.setup_queues_and_policies()
380
+ end
381
+
382
+ test "setting up queues and policies should handle ephemeral errors" do
383
+ client = Client.new
384
+ pub = Publisher.new(client)
385
+ client.register_queue("queue")
386
+ pub.servers = %w(a b)
387
+ pub.stubs(:queue).raises(StandardError)
388
+
389
+ s = sequence("setup")
390
+ pub.expects(:set_current_server).with("a").in_sequence(s)
391
+ pub.expects(:set_current_server).with("b").in_sequence(s)
392
+
393
+ pub.setup_queues_and_policies()
353
394
  end
354
395
 
355
396
  test "reports whether it has been throttled" do
@@ -516,10 +557,11 @@ module Beetle
516
557
  end
517
558
  end
518
559
 
519
-
520
560
  class RPCTest < Minitest::Test
521
561
  def setup
522
- @client = Client.new
562
+ @config = Configuration.new
563
+ @config.servers = ENV['RABBITMQ_SERVERS'].split(',').first if ENV['RABBITMQ_SERVERS']
564
+ @client = Client.new(@config)
523
565
  @pub = Publisher.new(@client)
524
566
  @client.register_message(:test, :exchange => :some_exchange)
525
567
  end
@@ -52,7 +52,9 @@ module Beetle
52
52
 
53
53
  class SubscriberPauseAndResumeTest < Minitest::Test
54
54
  def setup
55
- @client = Client.new
55
+ @config = Configuration.new
56
+ @config.servers = "localhost:5672"
57
+ @client = Client.new(@config)
56
58
  @sub = @client.send(:subscriber)
57
59
  @sub.servers << "localhost:7777"
58
60
  @server1, @server2 = @sub.servers
@@ -127,7 +129,7 @@ module Beetle
127
129
  @sub = @client.send(:subscriber)
128
130
  end
129
131
 
130
- test "subscribers server list should contain addtional subcription hosts" do
132
+ test "subscribers server list should contain additional subcription hosts" do
131
133
  assert_equal ["localhost:5672", "localhost:1234"], @sub.servers
132
134
  end
133
135
  end
@@ -168,6 +170,17 @@ module Beetle
168
170
  @sub.send(:bind_queues, %W(x y))
169
171
  end
170
172
 
173
+ test "binding queues with many bindings should create it only once" do
174
+ @client.register_queue(:x, :exchange => 'test_exchange')
175
+ @client.register_binding(:x, :exchange => 'test_exchange', :key => 'sir-message-a-lot')
176
+ @client.register_handler(%w(x)){}
177
+ @sub.stubs(:exchange)
178
+ queue = mock("queue")
179
+ queue.expects(:bind).twice
180
+ @sub.expects(:declare_queue!).returns(queue).once
181
+ @sub.send(:bind_queues, %W(x))
182
+ end
183
+
171
184
  test "subscribing to queues should subscribe on all queues" do
172
185
  @client.register_queue(:x)
173
186
  @client.register_queue(:y)
@@ -331,7 +344,9 @@ module Beetle
331
344
 
332
345
  class SubscriptionTest < Minitest::Test
333
346
  def setup
334
- @client = Client.new
347
+ @config = Configuration.new
348
+ @config.servers = "locahost:5672"
349
+ @client = Client.new(@config)
335
350
  @sub = @client.send(:subscriber)
336
351
  end
337
352