beetle 0.3.0.rc.2 → 0.3.0.rc.5
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.
- data/README.rdoc +1 -1
- data/RELEASE_NOTES.rdoc +5 -0
- data/Rakefile +2 -6
- data/beetle.gemspec +13 -6
- data/examples/nonexistent_server.rb +28 -0
- data/examples/redundant.rb +1 -1
- data/examples/rpc.rb +3 -3
- data/lib/beetle/base.rb +4 -0
- data/lib/beetle/client.rb +1 -1
- data/lib/beetle/message.rb +3 -2
- data/lib/beetle/redis_configuration_client.rb +1 -1
- data/lib/beetle/redis_configuration_server.rb +4 -3
- data/lib/beetle/subscriber.rb +67 -44
- data/lib/beetle/version.rb +3 -0
- data/lib/beetle.rb +23 -8
- data/test/beetle/amqp_gem_behavior_test.rb +30 -0
- data/test/beetle/base_test.rb +4 -0
- data/test/beetle/deduplication_store_test.rb +1 -1
- data/test/beetle/redis_ext_test.rb +3 -5
- data/test/beetle/subscriber_test.rb +114 -78
- data/test/colorized_test_output.rb +25 -0
- data/test/test_helper.rb +4 -6
- metadata +165 -199
- data/examples/test_publisher.rb +0 -32
data/README.rdoc
CHANGED
@@ -58,7 +58,7 @@ windows and execute the following commands:
|
|
58
58
|
|
59
59
|
To set up a redundant messaging system you will need
|
60
60
|
* at least 2 AMQP servers (we use {RabbitMQ}[http://www.rabbitmq.com/])
|
61
|
-
* at least one {Redis}[http://github.com/antirez/redis] server (better are two in a master/slave setup)
|
61
|
+
* at least one {Redis}[http://github.com/antirez/redis] server (better are two in a master/slave setup, see REDIS_AUTO_FAILOVER.rdoc)
|
62
62
|
|
63
63
|
== Gem Dependencies
|
64
64
|
|
data/RELEASE_NOTES.rdoc
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
= Release Notes
|
2
2
|
|
3
|
+
== Version 0.3.0.rc.3
|
4
|
+
|
5
|
+
* use hiredis as the redis backend, which overcomes lack of proper time-outs in the "generic" redis-rb
|
6
|
+
gem for Ruby 1.9
|
7
|
+
|
3
8
|
== Version 0.2.9.8
|
4
9
|
|
5
10
|
* since version 2.0, RabbitMQ supports Basic.reject(:requeue => true). we use it now too,
|
data/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'rcov/rcovtask'
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
|
4
6
|
# rake 0.9.2 hack to supress deprecation warnings caused by cucumber
|
5
7
|
include Rake::DSL if RAKEVERSION >= "0.9"
|
6
8
|
require 'cucumber/rake/task'
|
@@ -30,7 +32,6 @@ namespace :test do
|
|
30
32
|
end if RUBY_PLATFORM =~ /darwin/
|
31
33
|
end
|
32
34
|
|
33
|
-
|
34
35
|
namespace :beetle do
|
35
36
|
task :test do
|
36
37
|
Beetle::Client.new.test
|
@@ -108,8 +109,3 @@ Rake::RDocTask.new do |rdoc|
|
|
108
109
|
rdoc.rdoc_files.include('MIT-LICENSE')
|
109
110
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
110
111
|
end
|
111
|
-
|
112
|
-
desc "build the beetle gem"
|
113
|
-
task :build do
|
114
|
-
system("gem build beetle.gemspec")
|
115
|
-
end
|
data/beetle.gemspec
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "beetle/version"
|
4
|
+
|
1
5
|
Gem::Specification.new do |s|
|
2
6
|
s.name = "beetle"
|
3
|
-
s.version =
|
7
|
+
s.version = Beetle::VERSION
|
4
8
|
s.required_rubygems_version = ">= 1.3.7"
|
5
|
-
s.authors = ["Stefan Kaes", "Pascal Friederich", "Ali Jelveh", "Sebastian Roebke"]
|
9
|
+
s.authors = ["Stefan Kaes", "Pascal Friederich", "Ali Jelveh", "Sebastian Roebke", "Larry Baltz"]
|
6
10
|
s.date = Time.now.strftime('%Y-%m-%d')
|
7
11
|
s.default_executable = "beetle"
|
8
12
|
s.description = "A highly available, reliable messaging infrastructure"
|
9
13
|
s.summary = "High Availability AMQP Messaging with Redundant Queues"
|
10
|
-
s.email = "
|
14
|
+
s.email = "opensource@xing.com"
|
11
15
|
s.executables = ["beetle"]
|
12
16
|
s.extra_rdoc_files = Dir['**/*.rdoc'] + %w(MIT-LICENSE)
|
13
17
|
s.files = Dir['{examples,lib}/**/*.rb'] + Dir['{features,script}/**/*'] + %w(beetle.gemspec Rakefile)
|
@@ -29,9 +33,12 @@ Gem::Specification.new do |s|
|
|
29
33
|
|
30
34
|
s.specification_version = 3
|
31
35
|
s.add_runtime_dependency("uuid4r", [">= 0.1.2"])
|
32
|
-
s.add_runtime_dependency("bunny", ["
|
33
|
-
s.add_runtime_dependency("redis", ["= 2.0
|
34
|
-
s.add_runtime_dependency("
|
36
|
+
s.add_runtime_dependency("bunny", ["= 0.7.8"])
|
37
|
+
s.add_runtime_dependency("redis", ["= 2.2.0"])
|
38
|
+
s.add_runtime_dependency("hiredis", ["= 0.3.2"])
|
39
|
+
s.add_runtime_dependency("amq-client", ["= 0.8.3"])
|
40
|
+
s.add_runtime_dependency("amq-protocol", ["= 0.8.1"])
|
41
|
+
s.add_runtime_dependency("amqp", ["= 0.8.0"])
|
35
42
|
s.add_runtime_dependency("activesupport", [">= 2.3.4"])
|
36
43
|
s.add_runtime_dependency("daemons", [">= 1.0.10"])
|
37
44
|
s.add_development_dependency("rake", [">= 0.8.7"])
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# nonexistent_server.rb
|
2
|
+
# this example shows what happens when you try connect to a nonexistent server
|
3
|
+
#
|
4
|
+
# start it with ruby nonexistent_server.rb
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require File.expand_path("../lib/beetle", File.dirname(__FILE__))
|
8
|
+
|
9
|
+
# set Beetle log level to info, less noisy than debug
|
10
|
+
Beetle.config.logger.level = Logger::INFO
|
11
|
+
|
12
|
+
Beetle.config.servers = "unknown.railsexpress.de:5672"
|
13
|
+
|
14
|
+
# setup client
|
15
|
+
client = Beetle::Client.new
|
16
|
+
client.register_queue(:test)
|
17
|
+
client.register_message(:test)
|
18
|
+
|
19
|
+
# register our handler to the message, check out the message.rb for more stuff you can get from the message object
|
20
|
+
client.register_handler(:test) {|message| puts "got message: #{message.data}"}
|
21
|
+
|
22
|
+
# start listening
|
23
|
+
# this starts the event machine event loop using EM.run
|
24
|
+
# the block passed to listen will be yielded as the last step of the setup process
|
25
|
+
client.listen do
|
26
|
+
EM.add_timer(10) { client.stop_listening }
|
27
|
+
end
|
28
|
+
|
data/examples/redundant.rb
CHANGED
@@ -58,7 +58,7 @@ end
|
|
58
58
|
# this starts the event machine event loop using EM.run
|
59
59
|
# the block passed to listen will be yielded as the last step of the setup process
|
60
60
|
client.listen do
|
61
|
-
EM.add_timer(0.
|
61
|
+
EM.add_timer(0.2) { client.stop_listening }
|
62
62
|
end
|
63
63
|
|
64
64
|
puts "Received #{k} test messages"
|
data/examples/rpc.rb
CHANGED
@@ -3,7 +3,7 @@ require "rubygems"
|
|
3
3
|
require File.expand_path(File.dirname(__FILE__)+"/../lib/beetle")
|
4
4
|
|
5
5
|
# suppress debug messages
|
6
|
-
Beetle.config.logger.level = Logger::
|
6
|
+
Beetle.config.logger.level = Logger::INFO
|
7
7
|
Beetle.config.servers = "localhost:5672, localhost:5673"
|
8
8
|
# instantiate a client
|
9
9
|
|
@@ -28,12 +28,12 @@ if ARGV.include?("--server")
|
|
28
28
|
trap("INT") { puts "stopped echo server"; client.stop_listening }
|
29
29
|
end
|
30
30
|
else
|
31
|
-
n =
|
31
|
+
n = 10000
|
32
32
|
ms = Benchmark.ms do
|
33
33
|
n.times do |i|
|
34
34
|
content = "Hello #{i}"
|
35
35
|
# puts "performing RPC with message content '#{content}'"
|
36
|
-
status, result = client.rpc(:echo, content)
|
36
|
+
status, result = client.rpc(:echo, content, :persistent => false)
|
37
37
|
# puts "status #{status}"
|
38
38
|
# puts "result #{result}"
|
39
39
|
# puts
|
data/lib/beetle/base.rb
CHANGED
data/lib/beetle/client.rb
CHANGED
data/lib/beetle/message.rb
CHANGED
@@ -73,9 +73,10 @@ module Beetle
|
|
73
73
|
|
74
74
|
# extracts various values form the AMQP header properties
|
75
75
|
def decode #:nodoc:
|
76
|
-
|
76
|
+
# p header.attributes
|
77
|
+
amqp_headers = header.attributes
|
77
78
|
@uuid = amqp_headers[:message_id]
|
78
|
-
headers = amqp_headers[:headers]
|
79
|
+
headers = amqp_headers[:headers].symbolize_keys
|
79
80
|
@format_version = headers[:format_version].to_i
|
80
81
|
@flags = headers[:flags].to_i
|
81
82
|
@expires_at = headers[:expires_at].to_i
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Beetle
|
2
2
|
# A RedisConfigurationServer is the supervisor part of beetle's
|
3
|
-
# redis failover solution
|
3
|
+
# redis failover solution.
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# A single instance of RedisConfigurationServer works as a supervisor for
|
6
6
|
# several RedisConfigurationClient instances. It is responsible for watching
|
7
7
|
# the redis master and electing and publishing a new master in case of failure.
|
8
8
|
#
|
@@ -75,6 +75,7 @@ module Beetle
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
# called by the message dispatcher when a "client_started" message from a RedisConfigurationClient is received
|
78
79
|
def client_started(payload)
|
79
80
|
id = payload["id"]
|
80
81
|
if client_id_valid?(id)
|
@@ -186,7 +187,7 @@ module Beetle
|
|
186
187
|
end
|
187
188
|
known_client
|
188
189
|
end
|
189
|
-
|
190
|
+
|
190
191
|
def client_id_valid?(client_id)
|
191
192
|
@client_ids.include?(client_id)
|
192
193
|
end
|
data/lib/beetle/subscriber.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'amqp'
|
2
|
-
require 'mq'
|
3
2
|
|
4
3
|
module Beetle
|
5
4
|
# Manages subscriptions and message processing on the receiver side of things.
|
@@ -10,9 +9,10 @@ module Beetle
|
|
10
9
|
super
|
11
10
|
@servers.concat @client.additional_subscription_servers
|
12
11
|
@handlers = {}
|
13
|
-
@
|
14
|
-
@
|
12
|
+
@connections = {}
|
13
|
+
@channels = {}
|
15
14
|
@subscriptions = {}
|
15
|
+
@listened_queues = []
|
16
16
|
end
|
17
17
|
|
18
18
|
# the client calls this method to subscribe to a list of queues.
|
@@ -24,11 +24,12 @@ module Beetle
|
|
24
24
|
#
|
25
25
|
# yields before entering the eventmachine loop (if a block was given)
|
26
26
|
def listen_queues(queues) #:nodoc:
|
27
|
+
@listened_queues = queues
|
28
|
+
@exchanges_for_queues = exchanges_for_queues(queues)
|
27
29
|
EM.run do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
subscribe_queues(queues)
|
30
|
+
each_server do
|
31
|
+
connect_server connection_settings
|
32
|
+
end
|
32
33
|
yield if block_given?
|
33
34
|
end
|
34
35
|
end
|
@@ -47,10 +48,10 @@ module Beetle
|
|
47
48
|
|
48
49
|
# closes all AMQP connections and stops the eventmachine loop
|
49
50
|
def stop! #:nodoc:
|
50
|
-
if @
|
51
|
+
if @connections.empty?
|
51
52
|
EM.stop_event_loop
|
52
53
|
else
|
53
|
-
server, connection = @
|
54
|
+
server, connection = @connections.shift
|
54
55
|
logger.debug "Beetle: closing connection to #{server}"
|
55
56
|
connection.close { stop! }
|
56
57
|
end
|
@@ -74,30 +75,19 @@ module Beetle
|
|
74
75
|
end
|
75
76
|
|
76
77
|
def create_exchanges(exchanges)
|
77
|
-
|
78
|
-
exchanges.each { |name| exchange(name) }
|
79
|
-
end
|
78
|
+
exchanges.each { |name| exchange(name) }
|
80
79
|
end
|
81
80
|
|
82
81
|
def bind_queues(queues)
|
83
|
-
|
84
|
-
queues.each { |name| queue(name) }
|
85
|
-
end
|
82
|
+
queues.each { |name| queue(name) }
|
86
83
|
end
|
87
84
|
|
88
85
|
def subscribe_queues(queues)
|
89
|
-
|
90
|
-
queues.each { |name| subscribe(name) if @handlers.include?(name) }
|
91
|
-
end
|
86
|
+
queues.each { |name| subscribe(name) if @handlers.include?(name) }
|
92
87
|
end
|
93
88
|
|
94
|
-
|
95
|
-
|
96
|
-
# (instead of filling it). this is necesssary to ensure that one subscriber always just
|
97
|
-
# handles one single message. we cannot ensure reliability if the buffer is filled with
|
98
|
-
# messages and crashes.
|
99
|
-
def mq(server=@server)
|
100
|
-
@mqs[server] ||= MQ.new(amqp_connection).prefetch(1)
|
89
|
+
def channel(server=@server)
|
90
|
+
@channels[server]
|
101
91
|
end
|
102
92
|
|
103
93
|
def subscriptions(server=@server)
|
@@ -116,12 +106,8 @@ module Beetle
|
|
116
106
|
callback = create_subscription_callback(queue_name, amqp_queue_name, handler, opts)
|
117
107
|
keys = opts.slice(*SUBSCRIPTION_KEYS).merge(:key => "#", :ack => true)
|
118
108
|
logger.debug "Beetle: subscribing to queue #{amqp_queue_name} with key # on server #{@server}"
|
119
|
-
|
120
|
-
|
121
|
-
subscriptions[queue_name] = [keys, callback]
|
122
|
-
rescue MQ::Error
|
123
|
-
error("Beetle: binding multiple handlers for the same queue isn't possible.")
|
124
|
-
end
|
109
|
+
queues[queue_name].subscribe(keys, &callback)
|
110
|
+
subscriptions[queue_name] = [keys, callback]
|
125
111
|
end
|
126
112
|
|
127
113
|
def pause(queue_name)
|
@@ -147,13 +133,14 @@ module Beetle
|
|
147
133
|
if result.reject?
|
148
134
|
sleep 1
|
149
135
|
header.reject(:requeue => true)
|
150
|
-
elsif reply_to = header.
|
136
|
+
elsif reply_to = header.attributes[:reply_to]
|
137
|
+
# logger.info "Beetle: sending reply to queue #{reply_to}"
|
151
138
|
# require 'ruby-debug'
|
152
139
|
# Debugger.start
|
153
140
|
# debugger
|
154
141
|
status = result == Beetle::RC::OK ? "OK" : "FAILED"
|
155
|
-
exchange =
|
156
|
-
exchange.publish(m.handler_result.to_s, :headers => {:status => status})
|
142
|
+
exchange = AMQP::Exchange.new(channel(server), :direct, "")
|
143
|
+
exchange.publish(m.handler_result.to_s, :routing_key => reply_to, :persistent => false, :headers => {:status => status})
|
157
144
|
end
|
158
145
|
# logger.debug "Beetle: processed message"
|
159
146
|
rescue Exception
|
@@ -168,27 +155,63 @@ module Beetle
|
|
168
155
|
end
|
169
156
|
|
170
157
|
def create_exchange!(name, opts)
|
171
|
-
|
158
|
+
channel.__send__(opts[:type], name, opts.slice(*EXCHANGE_CREATION_KEYS))
|
172
159
|
end
|
173
160
|
|
174
161
|
def bind_queue!(queue_name, creation_keys, exchange_name, binding_keys)
|
175
|
-
queue =
|
162
|
+
queue = channel.queue(queue_name, creation_keys)
|
176
163
|
exchange = exchange(exchange_name)
|
177
164
|
queue.bind(exchange, binding_keys)
|
178
165
|
queue
|
179
166
|
end
|
180
167
|
|
181
|
-
def
|
182
|
-
|
168
|
+
def connection_settings
|
169
|
+
{
|
170
|
+
:host => current_host, :port => current_port, :logging => false,
|
171
|
+
:user => Beetle.config.user, :pass => Beetle.config.password, :vhost => Beetle.config.vhost,
|
172
|
+
:on_tcp_connection_failure => on_tcp_connection_failure
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
def on_tcp_connection_failure
|
177
|
+
Proc.new do |settings|
|
178
|
+
logger.warn "Beetle: connection failed: #{server_from_settings(settings)}"
|
179
|
+
EM::Timer.new(10) { connect_server(settings) }
|
180
|
+
end
|
183
181
|
end
|
184
182
|
|
185
|
-
def
|
186
|
-
#
|
187
|
-
|
188
|
-
|
189
|
-
con.instance_variable_set("@on_disconnect", proc{ con.__send__(:reconnect) })
|
190
|
-
con
|
183
|
+
def on_tcp_connection_loss(connection, settings)
|
184
|
+
# reconnect in 10 seconds, without enforcement
|
185
|
+
logger.warn "Beetle: lost connection: #{server_from_settings(settings)}. reconnecting."
|
186
|
+
connection.reconnect(false, 10)
|
191
187
|
end
|
192
188
|
|
189
|
+
def connect_server(settings)
|
190
|
+
server = server_from_settings settings
|
191
|
+
logger.info "Beetle: connecting to rabbit #{server}"
|
192
|
+
AMQP.connect(settings) do |connection|
|
193
|
+
connection.on_tcp_connection_loss(&method(:on_tcp_connection_loss))
|
194
|
+
@connections[server] = connection
|
195
|
+
open_channel_and_subscribe(connection, settings)
|
196
|
+
end
|
197
|
+
rescue EventMachine::ConnectionError => e
|
198
|
+
# something serious went wrong, for example DNS lookup failure
|
199
|
+
# in this case, the on_tcp_connection_failure callback is never called automatically
|
200
|
+
logger.error "Beetle: connection failed: #{e.class}(#{e})"
|
201
|
+
settings[:on_tcp_connection_failure].call(settings)
|
202
|
+
end
|
203
|
+
|
204
|
+
def open_channel_and_subscribe(connection, settings)
|
205
|
+
server = server_from_settings settings
|
206
|
+
AMQP::Channel.new(connection) do |channel|
|
207
|
+
channel.auto_recovery = true
|
208
|
+
channel.prefetch(1)
|
209
|
+
set_current_server server
|
210
|
+
@channels[server] = channel
|
211
|
+
create_exchanges(@exchanges_for_queues)
|
212
|
+
bind_queues(@listened_queues)
|
213
|
+
subscribe_queues(@listened_queues)
|
214
|
+
end
|
215
|
+
end
|
193
216
|
end
|
194
217
|
end
|
data/lib/beetle.rb
CHANGED
@@ -1,12 +1,27 @@
|
|
1
1
|
$:.unshift(File.expand_path('..', __FILE__))
|
2
2
|
require 'bunny'
|
3
3
|
require 'uuid4r'
|
4
|
+
require 'redis/connection/hiredis' # require *before* redis as specified in the redis-rb gem docs
|
5
|
+
require 'redis'
|
4
6
|
require 'active_support'
|
5
7
|
require 'active_support/core_ext'
|
6
|
-
require 'redis'
|
7
8
|
require 'set'
|
9
|
+
require 'socket'
|
8
10
|
|
9
11
|
module Beetle
|
12
|
+
Timer = if RUBY_VERSION < "1.9"
|
13
|
+
begin
|
14
|
+
require 'system_timer'
|
15
|
+
SystemTimer
|
16
|
+
rescue Exception => e
|
17
|
+
warn "WARNING: It's highly recommended to install the SystemTimer gem: `gem install SystemTimer -v '=1.2.1'` See: http://ph7spot.com/musings/system-timer" if RUBY_VERSION < "1.9"
|
18
|
+
require 'timeout'
|
19
|
+
Timeout
|
20
|
+
end
|
21
|
+
else
|
22
|
+
require 'timeout'
|
23
|
+
Timeout
|
24
|
+
end
|
10
25
|
|
11
26
|
# abstract superclass for Beetle specific exceptions
|
12
27
|
class Error < StandardError; end
|
@@ -32,6 +47,13 @@ module Beetle
|
|
32
47
|
# AMQP options for subscribing to queues
|
33
48
|
SUBSCRIPTION_KEYS = [:ack, :key]
|
34
49
|
|
50
|
+
# determine the fully qualified domainname of the host we're running on
|
51
|
+
def self.hostname
|
52
|
+
name = Socket.gethostname
|
53
|
+
parts = name.split('.')
|
54
|
+
parts.size > 1 ? name : Socket.gethostbyname(parts.first).first
|
55
|
+
end
|
56
|
+
|
35
57
|
# use ruby's autoload mechanism for loading beetle classes
|
36
58
|
lib_dir = File.expand_path(File.dirname(__FILE__) + '/beetle/')
|
37
59
|
Dir["#{lib_dir}/*.rb"].each do |libfile|
|
@@ -56,11 +78,4 @@ module Beetle
|
|
56
78
|
def self.reraise_expectation_errors! #:nodoc:
|
57
79
|
end
|
58
80
|
end
|
59
|
-
|
60
|
-
Timer = begin
|
61
|
-
RUBY_VERSION < "1.9" ? SystemTimer : Timeout
|
62
|
-
rescue NameError
|
63
|
-
warn "WARNING: It's highly recommended to install the SystemTimer gem: `gem install SystemTimer -v '=1.2.1'` See: http://ph7spot.com/musings/system-timer" if RUBY_VERSION < "1.9"
|
64
|
-
Timeout
|
65
|
-
end
|
66
81
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'amqp'
|
4
|
+
|
5
|
+
class AMQPGemBehaviorTest < Test::Unit::TestCase
|
6
|
+
test "subscribing twice to the same queue raises a RuntimeError which throws us out of the event loop" do
|
7
|
+
begin
|
8
|
+
@exception = nil
|
9
|
+
EM.run do
|
10
|
+
AMQP.start do |connection|
|
11
|
+
begin
|
12
|
+
EM::Timer.new(1){ connection.close { EM.stop }}
|
13
|
+
channel = AMQP::Channel.new(connection)
|
14
|
+
channel.on_error { puts "woot"}
|
15
|
+
exchange = channel.topic("beetle_tests")
|
16
|
+
queue = AMQP::Queue.new(channel)
|
17
|
+
queue.bind(exchange, :key => "#")
|
18
|
+
queue.subscribe { }
|
19
|
+
queue.subscribe { }
|
20
|
+
rescue
|
21
|
+
# we never get here, because the subscription is deferred
|
22
|
+
# the only known way to avoid this is to use the block version of AMQP::Queue.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue Exception => @exception
|
27
|
+
end
|
28
|
+
assert @exception
|
29
|
+
end
|
30
|
+
end
|
data/test/beetle/base_test.rb
CHANGED
@@ -48,5 +48,9 @@ module Beetle
|
|
48
48
|
@bs.send(:set_current_server, "xxx:123")
|
49
49
|
assert_equal "xxx:123", @bs.server
|
50
50
|
end
|
51
|
+
|
52
|
+
test "server_from_settings should create a valid server string from an AMQP settings hash" do
|
53
|
+
assert_equal "goofy:123", @bs.send(:server_from_settings, {:host => "goofy", :port => 123})
|
54
|
+
end
|
51
55
|
end
|
52
56
|
end
|
@@ -55,11 +55,9 @@ module Beetle
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
class
|
59
|
-
test
|
60
|
-
|
61
|
-
r.client.expects(:with_timeout).with(1).raises(Timeout::Error)
|
62
|
-
assert_equal({}, r.info_with_rescue)
|
58
|
+
class HiredisLoadedTest < Test::Unit::TestCase
|
59
|
+
test 'should be using hiredis instead of the redis ruby backend' do
|
60
|
+
assert defined?(Hiredis)
|
63
61
|
end
|
64
62
|
end
|
65
63
|
end
|