right_amqp 0.2.0
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/LICENSE +20 -0
- data/README.rdoc +216 -0
- data/Rakefile +70 -0
- data/lib/right_amqp.rb +28 -0
- data/lib/right_amqp/amqp.rb +115 -0
- data/lib/right_amqp/amqp/buffer.rb +395 -0
- data/lib/right_amqp/amqp/client.rb +282 -0
- data/lib/right_amqp/amqp/frame.rb +124 -0
- data/lib/right_amqp/amqp/protocol.rb +212 -0
- data/lib/right_amqp/amqp/server.rb +99 -0
- data/lib/right_amqp/amqp/spec.rb +832 -0
- data/lib/right_amqp/amqp/version.rb +3 -0
- data/lib/right_amqp/ext/blankslate.rb +7 -0
- data/lib/right_amqp/ext/em.rb +8 -0
- data/lib/right_amqp/ext/emfork.rb +69 -0
- data/lib/right_amqp/ha_client.rb +25 -0
- data/lib/right_amqp/ha_client/broker_client.rb +690 -0
- data/lib/right_amqp/ha_client/ha_broker_client.rb +1185 -0
- data/lib/right_amqp/mq.rb +866 -0
- data/lib/right_amqp/mq/exchange.rb +304 -0
- data/lib/right_amqp/mq/header.rb +33 -0
- data/lib/right_amqp/mq/logger.rb +89 -0
- data/lib/right_amqp/mq/queue.rb +456 -0
- data/lib/right_amqp/mq/rpc.rb +100 -0
- data/right_amqp.gemspec +57 -0
- data/spec/amqp/client_reconnect_spec.rb +105 -0
- data/spec/ha_client/broker_client_spec.rb +936 -0
- data/spec/ha_client/ha_broker_client_spec.rb +1385 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +56 -0
- metadata +141 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
class MQ
|
2
|
+
# Basic RPC (remote procedure call) facility.
|
3
|
+
#
|
4
|
+
# Needs more detail and explanation.
|
5
|
+
#
|
6
|
+
# EM.run do
|
7
|
+
# server = MQ.rpc('hash table node', Hash)
|
8
|
+
#
|
9
|
+
# client = MQ.rpc('hash table node')
|
10
|
+
# client[:now] = Time.now
|
11
|
+
# client[:one] = 1
|
12
|
+
#
|
13
|
+
# client.values do |res|
|
14
|
+
# p 'client', :values => res
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# client.keys do |res|
|
18
|
+
# p 'client', :keys => res
|
19
|
+
# EM.stop_event_loop
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class RPC < BlankSlate
|
24
|
+
# Takes a channel, queue and optional object.
|
25
|
+
#
|
26
|
+
# The optional object may be a class name, module name or object
|
27
|
+
# instance. When given a class or module name, the object is instantiated
|
28
|
+
# during this setup. The passed queue is automatically subscribed to so
|
29
|
+
# it passes all messages (and their arguments) to the object.
|
30
|
+
#
|
31
|
+
# Marshalling and unmarshalling the objects is handled internally. This
|
32
|
+
# marshalling is subject to the same restrictions as defined in the
|
33
|
+
# Marshal[http://ruby-doc.org/core/classes/Marshal.html] standard
|
34
|
+
# library. See that documentation for further reference.
|
35
|
+
#
|
36
|
+
# When the optional object is not passed, the returned rpc reference is
|
37
|
+
# used to send messages and arguments to the queue. See #method_missing
|
38
|
+
# which does all of the heavy lifting with the proxy. Some client
|
39
|
+
# elsewhere must call this method *with* the optional block so that
|
40
|
+
# there is a valid destination. Failure to do so will just enqueue
|
41
|
+
# marshalled messages that are never consumed.
|
42
|
+
#
|
43
|
+
def initialize mq, queue, obj = nil
|
44
|
+
@mq = mq
|
45
|
+
@mq.rpcs[queue] ||= self
|
46
|
+
|
47
|
+
if obj
|
48
|
+
@obj = case obj
|
49
|
+
when ::Class
|
50
|
+
obj.new
|
51
|
+
when ::Module
|
52
|
+
(::Class.new do include(obj) end).new
|
53
|
+
else
|
54
|
+
obj
|
55
|
+
end
|
56
|
+
|
57
|
+
@mq.queue(queue).subscribe(:ack=>true){ |info, request|
|
58
|
+
method, *args = ::Marshal.load(request)
|
59
|
+
ret = @obj.__send__(method, *args)
|
60
|
+
|
61
|
+
info.ack
|
62
|
+
|
63
|
+
if info.reply_to
|
64
|
+
@mq.queue(info.reply_to).publish(::Marshal.dump(ret), :key => info.reply_to, :message_id => info.message_id)
|
65
|
+
end
|
66
|
+
}
|
67
|
+
else
|
68
|
+
@callbacks ||= {}
|
69
|
+
# XXX implement and use queue(nil)
|
70
|
+
@queue = @mq.queue(@name = "random identifier #{::Kernel.rand(999_999_999_999)}", :auto_delete => true).subscribe{|info, msg|
|
71
|
+
if blk = @callbacks.delete(info.message_id)
|
72
|
+
blk.call ::Marshal.load(msg)
|
73
|
+
end
|
74
|
+
}
|
75
|
+
@remote = @mq.queue(queue)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Calling MQ.rpc(*args) returns a proxy object without any methods beyond
|
80
|
+
# those in Object. All calls to the proxy are handled by #method_missing which
|
81
|
+
# works to marshal and unmarshal all method calls and their arguments.
|
82
|
+
#
|
83
|
+
# EM.run do
|
84
|
+
# server = MQ.rpc('hash table node', Hash)
|
85
|
+
# client = MQ.rpc('hash table node')
|
86
|
+
#
|
87
|
+
# # calls #method_missing on #[] which marshals the method name and
|
88
|
+
# # arguments to publish them to the remote
|
89
|
+
# client[:now] = Time.now
|
90
|
+
# ....
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
def method_missing meth, *args, &blk
|
94
|
+
# XXX use uuids instead
|
95
|
+
message_id = "random message id #{::Kernel.rand(999_999_999_999)}"
|
96
|
+
@callbacks[message_id] = blk if blk
|
97
|
+
@remote.publish(::Marshal.dump([meth, *args]), :reply_to => blk ? @name : nil, :message_id => message_id)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/right_amqp.gemspec
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*-ruby-*-
|
2
|
+
# Copyright: Copyright (c) 2012 RightScale, Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# 'Software'), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
|
25
|
+
Gem::Specification.new do |spec|
|
26
|
+
spec.name = 'right_amqp'
|
27
|
+
spec.version = '0.2.0'
|
28
|
+
spec.authors = ['Lee Kirchhoff']
|
29
|
+
spec.email = 'lee@rightscale.com'
|
30
|
+
spec.homepage = 'https://github.com/rightscale/right_amqp'
|
31
|
+
spec.platform = Gem::Platform::RUBY
|
32
|
+
spec.summary = 'Client for interfacing to RightScale RabbitMQ broker using AMQP'
|
33
|
+
spec.has_rdoc = true
|
34
|
+
spec.rdoc_options = ["--main", "README.rdoc", "--title", "RightAMQP"]
|
35
|
+
spec.extra_rdoc_files = ["README.rdoc"]
|
36
|
+
spec.required_ruby_version = '>= 1.8.7'
|
37
|
+
spec.require_path = 'lib'
|
38
|
+
|
39
|
+
spec.add_dependency('right_support', '~> 1.2')
|
40
|
+
spec.add_dependency('eventmachine', '~> 0.12.10')
|
41
|
+
|
42
|
+
spec.description = <<-EOF
|
43
|
+
RightAMQP provides a high availability client for interfacing with the
|
44
|
+
RightScale RabbitMQ broker using the AMQP protocol. The AMQP version on which
|
45
|
+
this gem is based is 0.6.7 but beyond that it contains a number of bug fixes and
|
46
|
+
enhancements including reconnect, message return, heartbeat, and UTF-8 support.
|
47
|
+
The high availability is achieved by maintaining multiple broker connections
|
48
|
+
such that failed connections automatically reconnect and only connected
|
49
|
+
brokers are used when routing a message. Although the HABrokerClient class
|
50
|
+
is the intended primary means for accessing RabbitMQ services with this gem,
|
51
|
+
alternatively the underlying AMQP services may be used directly.
|
52
|
+
EOF
|
53
|
+
|
54
|
+
candidates = Dir.glob("{lib,spec}/**/*") +
|
55
|
+
["LICENSE", "README.rdoc", "Rakefile", "right_amqp.gemspec"]
|
56
|
+
spec.files = candidates.sort
|
57
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2012 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'right_amqp'))
|
25
|
+
|
26
|
+
describe AMQP::Client do
|
27
|
+
|
28
|
+
context 'with an incorrect AMQP password' do
|
29
|
+
|
30
|
+
include RightAMQP::SpecHelper
|
31
|
+
|
32
|
+
class SUT
|
33
|
+
include AMQP::Client
|
34
|
+
|
35
|
+
attr_accessor :reconnecting, :settings, :channels
|
36
|
+
end
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
setup_logger
|
40
|
+
@sut = flexmock(SUT.new)
|
41
|
+
@sut.reconnecting = false
|
42
|
+
@sut.settings = {:host => 'testhost', :port=>'12345'}
|
43
|
+
@sut.channels = {}
|
44
|
+
|
45
|
+
@sut.should_receive(:initialize)
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'and no :reconnect_delay' do
|
49
|
+
it 'should reconnect immediately' do
|
50
|
+
flexmock(EM).should_receive(:reconnect).once
|
51
|
+
flexmock(EM).should_receive(:add_timer).never
|
52
|
+
|
53
|
+
@sut.reconnect()
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'and a :reconnect_delay of true' do
|
58
|
+
it 'should reconnect immediately' do
|
59
|
+
@sut.settings[:reconnect_delay] = true
|
60
|
+
|
61
|
+
flexmock(EM).should_receive(:reconnect).once
|
62
|
+
flexmock(EM).should_receive(:add_timer).never
|
63
|
+
|
64
|
+
@sut.reconnect()
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'and a :reconnect_delay of 15 seconds' do
|
69
|
+
it 'should schedule a reconnect attempt in 15s' do
|
70
|
+
@sut.settings[:reconnect_delay] = 15
|
71
|
+
|
72
|
+
flexmock(EM).should_receive(:reconnect).never
|
73
|
+
flexmock(EM).should_receive(:add_timer).with(15, Proc).once
|
74
|
+
|
75
|
+
@sut.reconnect()
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'and a :reconnect_delay containing a Proc that returns 30' do
|
80
|
+
it 'should schedule a reconnect attempt in 30s' do
|
81
|
+
@sut.settings[:reconnect_delay] = Proc.new {30}
|
82
|
+
|
83
|
+
flexmock(EM).should_receive(:reconnect).never
|
84
|
+
flexmock(EM).should_receive(:add_timer).with(30, Proc).once
|
85
|
+
|
86
|
+
@sut.reconnect()
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'and a :reconnect_interval of 5 seconds' do
|
91
|
+
it 'should schedule reconnect attempts on a 5s interval' do
|
92
|
+
@sut.reconnecting = true
|
93
|
+
@sut.settings[:reconnect_delay] = 15
|
94
|
+
@sut.settings[:reconnect_interval] = 5
|
95
|
+
|
96
|
+
flexmock(EM).should_receive(:reconnect).never
|
97
|
+
flexmock(EM).should_receive(:add_timer).with(5, Proc).once
|
98
|
+
|
99
|
+
@sut.reconnect()
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,936 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2012 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'right_amqp'))
|
25
|
+
|
26
|
+
class RequestMock; end
|
27
|
+
class ResultMock; end
|
28
|
+
|
29
|
+
describe RightAMQP::BrokerClient do
|
30
|
+
|
31
|
+
include FlexMock::ArgumentTypes
|
32
|
+
include RightAMQP::SpecHelper
|
33
|
+
|
34
|
+
before(:each) do
|
35
|
+
setup_logger
|
36
|
+
@message = "message"
|
37
|
+
@packet = flexmock("packet", :class => RequestMock, :to_s => true, :version => [12, 12]).by_default
|
38
|
+
@serializer = flexmock("serializer")
|
39
|
+
@serializer.should_receive(:dump).and_return(@message).by_default
|
40
|
+
@serializer.should_receive(:load).with(@message).and_return(@packet).by_default
|
41
|
+
@exceptions = flexmock("exceptions")
|
42
|
+
@exceptions.should_receive(:track).never.by_default
|
43
|
+
@connection = flexmock("connection")
|
44
|
+
@connection.should_receive(:connection_status).by_default
|
45
|
+
flexmock(AMQP).should_receive(:connect).and_return(@connection).by_default
|
46
|
+
@channel = flexmock("AMQP connection channel")
|
47
|
+
@channel.should_receive(:connection).and_return(@connection).by_default
|
48
|
+
@identity = "rs-broker-localhost-5672"
|
49
|
+
@address = {:host => "localhost", :port => 5672, :index => 0}
|
50
|
+
@options = {}
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when initializing connection" do
|
54
|
+
|
55
|
+
before(:each) do
|
56
|
+
@amqp = flexmock(AMQP)
|
57
|
+
@amqp.should_receive(:connect).and_return(@connection).by_default
|
58
|
+
@channel.should_receive(:prefetch).never.by_default
|
59
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should create a broker with AMQP connection for specified address" do
|
63
|
+
@amqp.should_receive(:connect).with(hsh(:user => "user", :pass => "pass", :vhost => "vhost", :host => "localhost",
|
64
|
+
:port => 5672, :insist => true, :reconnect_interval => 10)).and_return(@connection).once
|
65
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, {:user => "user",
|
66
|
+
:pass => "pass", :vhost => "vhost", :insist => true,
|
67
|
+
:reconnect_interval => 10})
|
68
|
+
broker.host.should == "localhost"
|
69
|
+
broker.port.should == 5672
|
70
|
+
broker.index.should == 0
|
71
|
+
broker.queues.should == []
|
72
|
+
broker.summary.should == {:alias => "b0", :identity => @identity, :status => :connecting,
|
73
|
+
:disconnects => 0, :failures => 0, :retries => 0}
|
74
|
+
broker.usable?.should be_true
|
75
|
+
broker.connected?.should be_false
|
76
|
+
broker.failed?.should be_false
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should update state from existing client for given broker" do
|
80
|
+
existing = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
81
|
+
existing.__send__(:update_status, :disconnected)
|
82
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options, existing)
|
83
|
+
broker.summary.should == {:alias => "b0", :identity => @identity, :status => :connecting,
|
84
|
+
:disconnects => 1, :failures => 0, :retries => 0}
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should log an info message when it creates an AMQP connection" do
|
88
|
+
@logger.should_receive(:info).with(/Connecting to broker/).once
|
89
|
+
RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should log an error and set status to :failed if it fails to create an AMQP connection" do
|
93
|
+
@exceptions.should_receive(:track).once
|
94
|
+
@connection.should_receive(:close).once
|
95
|
+
@logger.should_receive(:info).once
|
96
|
+
@logger.should_receive(:error).with(/Failed connecting/).once
|
97
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_raise(Exception)
|
98
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
99
|
+
broker.summary.should == {:alias => "b0", :identity => @identity, :status => :failed,
|
100
|
+
:disconnects => 0, :failures => 1, :retries => 0}
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should set initialize connection status callback" do
|
104
|
+
@connection.should_receive(:connection_status).once
|
105
|
+
RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should set broker prefetch value if specified" do
|
109
|
+
@channel.should_receive(:prefetch).with(1).once
|
110
|
+
RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, {:prefetch => 1})
|
111
|
+
end
|
112
|
+
|
113
|
+
end # when initializing connection
|
114
|
+
|
115
|
+
context "when subscribing" do
|
116
|
+
|
117
|
+
before(:each) do
|
118
|
+
@info = flexmock("info", :ack => true).by_default
|
119
|
+
@serializer.should_receive(:load).with(@message).and_return(@packet).by_default
|
120
|
+
@direct = flexmock("direct")
|
121
|
+
@fanout = flexmock("fanout")
|
122
|
+
@bind = flexmock("bind")
|
123
|
+
@queue = flexmock("queue")
|
124
|
+
@queue.should_receive(:bind).and_return(@bind).by_default
|
125
|
+
@channel.should_receive(:queue).and_return(@queue).by_default
|
126
|
+
@channel.should_receive(:direct).and_return(@direct).by_default
|
127
|
+
@channel.should_receive(:fanout).and_return(@fanout).by_default
|
128
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should subscribe queue to exchange" do
|
132
|
+
@queue.should_receive(:bind).and_return(@bind).once
|
133
|
+
@bind.should_receive(:subscribe).once
|
134
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
135
|
+
broker.__send__(:update_status, :ready)
|
136
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}) {|_, _|}
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should subscribe queue to second exchange if specified" do
|
140
|
+
@queue.should_receive(:bind).and_return(@bind).twice
|
141
|
+
@bind.should_receive(:subscribe).once
|
142
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
143
|
+
broker.__send__(:update_status, :ready)
|
144
|
+
options = {:exchange2 => {:type => :fanout, :name => "exchange2", :options => {:durable => true}}}
|
145
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}, options) {|_, _|}
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should subscribe queue to exchange when still connecting" do
|
149
|
+
@bind.should_receive(:subscribe).once
|
150
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
151
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}) {|_, _|}
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should subscribe queue to empty exchange if no exchange specified" do
|
155
|
+
@queue.should_receive(:subscribe).once
|
156
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
157
|
+
broker.__send__(:update_status, :ready)
|
158
|
+
broker.subscribe({:name => "queue"}) {|b, p| p.should == nil}
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should store queues for future reference" do
|
162
|
+
@bind.should_receive(:subscribe).once
|
163
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
164
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"})
|
165
|
+
broker.queues.should == [@queue]
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should return true if subscribed successfully" do
|
169
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
170
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
171
|
+
result = broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"},
|
172
|
+
RequestMock => true) {|b, p| p.should == @packet}
|
173
|
+
result.should be_true
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return true if already subscribed and not try to resubscribe" do
|
177
|
+
@queue.should_receive(:name).and_return("queue").once
|
178
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
179
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
180
|
+
result = broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"},
|
181
|
+
RequestMock => true) {|b, p| p.should == @packet}
|
182
|
+
result.should be_true
|
183
|
+
result = broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}) {|_, _|}
|
184
|
+
result.should be_true
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should ack received message if requested" do
|
188
|
+
@info.should_receive(:ack).once
|
189
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
190
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
191
|
+
broker.__send__(:update_status, :ready)
|
192
|
+
result = broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"},
|
193
|
+
:ack => true, RequestMock => true) {|b, p| p.should == @packet}
|
194
|
+
result.should be_true
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should return false if client not usable" do
|
198
|
+
@queue.should_receive(:bind).and_return(@bind).never
|
199
|
+
@bind.should_receive(:subscribe).never
|
200
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
201
|
+
broker.__send__(:update_status, :disconnected)
|
202
|
+
broker.subscribe({:name => "queue"}).should be_false
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should receive message causing it to be unserialized and logged" do
|
206
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
207
|
+
@logger.should_receive(:info).with(/Subscribing/).once
|
208
|
+
@logger.should_receive(:info).with(/RECV/).once
|
209
|
+
@serializer.should_receive(:load).with(@message).and_return(@packet).once
|
210
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
211
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
212
|
+
broker.__send__(:update_status, :ready)
|
213
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"},
|
214
|
+
RequestMock => nil) {|b, p| p.class.should == RequestMock}
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should receive message and log exception if subscribe block fails" do
|
218
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
219
|
+
@logger.should_receive(:info).with(/Subscribing/).once
|
220
|
+
@logger.should_receive(:error).with(/Failed executing block/).once
|
221
|
+
@exceptions.should_receive(:track).once
|
222
|
+
@serializer.should_receive(:load).with(@message).and_return(@packet).once
|
223
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
224
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
225
|
+
broker.__send__(:update_status, :ready)
|
226
|
+
result = broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"},
|
227
|
+
RequestMock => nil) {|b, p| raise Exception}
|
228
|
+
result.should be_false
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should ignore 'nil' message when using ack" do
|
232
|
+
@logger.should_receive(:level).and_return(:debug)
|
233
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
234
|
+
@logger.should_receive(:info).with(/Subscribing/).once
|
235
|
+
@logger.should_receive(:debug).with(/nil message ignored/).once
|
236
|
+
@bind.should_receive(:subscribe).and_yield(@info, "nil").once
|
237
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
238
|
+
broker.__send__(:update_status, :ready)
|
239
|
+
called = 0
|
240
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}, :ack => true) { |b, m| called += 1 }
|
241
|
+
called.should == 0
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should ignore 'nil' message when not using ack" do
|
245
|
+
@logger.should_receive(:level).and_return(:debug)
|
246
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
247
|
+
@logger.should_receive(:info).with(/Subscribing/).once
|
248
|
+
@logger.should_receive(:debug).with(/nil message ignored/).once
|
249
|
+
@bind.should_receive(:subscribe).and_yield(@info, "nil").once
|
250
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
251
|
+
broker.__send__(:update_status, :ready)
|
252
|
+
called = 0
|
253
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}) { |b, m| called += 1 }
|
254
|
+
called.should == 0
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should not unserialize the message if requested" do
|
258
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
259
|
+
@logger.should_receive(:info).with(/Subscribing/).once
|
260
|
+
@logger.should_receive(:info).with(/^RECV/).never
|
261
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
262
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
263
|
+
broker.__send__(:update_status, :ready)
|
264
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}, :no_unserialize => true) do |b, m|
|
265
|
+
b.should == "rs-broker-localhost-5672"
|
266
|
+
m.should == @message
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should pass header with message if callback requires it" do
|
271
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
272
|
+
@logger.should_receive(:info).with(/Subscribing/).once
|
273
|
+
@logger.should_receive(:info).with(/^RECV/).never
|
274
|
+
@bind.should_receive(:subscribe).and_yield(@info, @message).once
|
275
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
276
|
+
broker.__send__(:update_status, :ready)
|
277
|
+
broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}, :no_unserialize => true) do |b, m, h|
|
278
|
+
b.should == "rs-broker-localhost-5672"
|
279
|
+
m.should == @message
|
280
|
+
h.should == @info
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should log an error if a subscribe fails" do
|
285
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
286
|
+
@logger.should_receive(:info).with(/RECV/).never
|
287
|
+
@logger.should_receive(:error).with(/Failed subscribing/).once
|
288
|
+
@exceptions.should_receive(:track).once
|
289
|
+
@bind.should_receive(:subscribe).and_raise(Exception)
|
290
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
291
|
+
broker.__send__(:update_status, :ready)
|
292
|
+
result = broker.subscribe({:name => "queue"}, {:type => :direct, :name => "exchange"}) {|b, p|}
|
293
|
+
result.should be_false
|
294
|
+
end
|
295
|
+
|
296
|
+
end # when subscribing
|
297
|
+
|
298
|
+
context "when receiving" do
|
299
|
+
|
300
|
+
it "should unserialize the message, log it, and return it" do
|
301
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
302
|
+
@logger.should_receive(:info).with(/^RECV/).once
|
303
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
304
|
+
broker.__send__(:receive, "queue", @message, RequestMock => nil).should == @packet
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should log a warning if the message is not of the right type and return nil" do
|
308
|
+
@logger.should_receive(:warning).with(/Received invalid.*packet type/).once
|
309
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
310
|
+
broker.__send__(:receive, "queue", @message).should be_nil
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should show the category in the warning message if specified" do
|
314
|
+
@logger.should_receive(:warning).with(/Received invalid xxxx packet type/).once
|
315
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
316
|
+
broker.__send__(:receive, "queue", @message, ResultMock => nil, :category => "xxxx")
|
317
|
+
end
|
318
|
+
|
319
|
+
it "should display broker alias in the log" do
|
320
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
321
|
+
@logger.should_receive(:info).with(/^RECV b0 /).once
|
322
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
323
|
+
broker.__send__(:receive, "queue", @message, RequestMock => nil)
|
324
|
+
end
|
325
|
+
|
326
|
+
it "should filter the packet display for :info level" do
|
327
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
328
|
+
@logger.should_receive(:info).with(/^RECV.*TO YOU/).once
|
329
|
+
@logger.should_receive(:debug).with(/^RECV.*TO YOU/).never
|
330
|
+
@packet.should_receive(:to_s).with([:to], :recv_version).and_return("TO YOU").once
|
331
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
332
|
+
broker.__send__(:receive, "queue", @message, RequestMock => [:to])
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should not filter the packet display for :debug level" do
|
336
|
+
@logger.should_receive(:level).and_return(:debug)
|
337
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
338
|
+
@logger.should_receive(:info).with(/^RECV.*ALL/).never
|
339
|
+
@logger.should_receive(:info).with(/^RECV.*ALL/).once
|
340
|
+
@packet.should_receive(:to_s).with(nil, :recv_version).and_return("ALL").once
|
341
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
342
|
+
broker.__send__(:receive, "queue", @message, RequestMock => [:to])
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should display additional data in log" do
|
346
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
347
|
+
@logger.should_receive(:info).with(/^RECV.*More data/).once
|
348
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
349
|
+
broker.__send__(:receive, "queue", @message, RequestMock => nil, :log_data => "More data")
|
350
|
+
end
|
351
|
+
|
352
|
+
it "should not log a message if requested not to" do
|
353
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
354
|
+
@logger.should_receive(:info).with(/^RECV/).never
|
355
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
356
|
+
broker.__send__(:receive, "queue", @message, RequestMock => nil, :no_log => true)
|
357
|
+
end
|
358
|
+
|
359
|
+
it "should not log a message if requested not to unless debug level" do
|
360
|
+
@logger.should_receive(:level).and_return(:debug)
|
361
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
362
|
+
@logger.should_receive(:info).with(/^RECV/).once
|
363
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
364
|
+
broker.__send__(:receive, "queue", @message, RequestMock => nil, :no_log => true)
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should log an error if exception prevents normal logging and should then return nil" do
|
368
|
+
@logger.should_receive(:error).with(/Failed receiving from queue/).once
|
369
|
+
@serializer.should_receive(:load).with(@message).and_raise(Exception).once
|
370
|
+
@exceptions.should_receive(:track).once
|
371
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
372
|
+
broker.__send__(:receive, "queue", @message).should be_nil
|
373
|
+
end
|
374
|
+
|
375
|
+
it "should make callback when there is a receive failure" do
|
376
|
+
@logger.should_receive(:error).with(/Failed receiving from queue/).once
|
377
|
+
@serializer.should_receive(:load).with(@message).and_raise(Exception).once
|
378
|
+
@exceptions.should_receive(:track).once
|
379
|
+
called = 0
|
380
|
+
callback = lambda { |msg, e| called += 1 }
|
381
|
+
options = {:exception_on_receive_callback => callback}
|
382
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, options)
|
383
|
+
broker.__send__(:receive, "queue", @message).should be_nil
|
384
|
+
called.should == 1
|
385
|
+
end
|
386
|
+
|
387
|
+
it "should display RE-RECV if the message being received is a retry" do
|
388
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
389
|
+
@logger.should_receive(:info).with(/^RE-RECV/).once
|
390
|
+
@packet.should_receive(:tries).and_return(["try1"]).once
|
391
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
392
|
+
broker.__send__(:receive, "queue", @message, RequestMock => nil).should == @packet
|
393
|
+
end
|
394
|
+
|
395
|
+
end # when receiving
|
396
|
+
|
397
|
+
context "when unsubscribing" do
|
398
|
+
|
399
|
+
before(:each) do
|
400
|
+
@direct = flexmock("direct")
|
401
|
+
@bind = flexmock("bind", :subscribe => true)
|
402
|
+
@queue = flexmock("queue", :bind => @bind, :name => "queue1")
|
403
|
+
@channel.should_receive(:queue).and_return(@queue).by_default
|
404
|
+
@channel.should_receive(:direct).and_return(@direct).by_default
|
405
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
406
|
+
end
|
407
|
+
|
408
|
+
it "should unsubscribe a queue by name" do
|
409
|
+
@queue.should_receive(:unsubscribe).once
|
410
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
411
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
412
|
+
broker.unsubscribe(["queue1"])
|
413
|
+
end
|
414
|
+
|
415
|
+
it "should ignore unsubscribe if queue unknown" do
|
416
|
+
@queue.should_receive(:unsubscribe).never
|
417
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
418
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
419
|
+
broker.unsubscribe(["queue2"])
|
420
|
+
end
|
421
|
+
|
422
|
+
it "should activate block after unsubscribing if provided" do
|
423
|
+
@queue.should_receive(:unsubscribe).and_yield.once
|
424
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
425
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
426
|
+
called = 0
|
427
|
+
broker.unsubscribe(["queue1"]) { called += 1 }
|
428
|
+
called.should == 1
|
429
|
+
end
|
430
|
+
|
431
|
+
it "should ignore the request if client not usable" do
|
432
|
+
@queue.should_receive(:unsubscribe).and_yield.never
|
433
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
434
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
435
|
+
broker.__send__(:update_status, :disconnected)
|
436
|
+
broker.unsubscribe(["queue1"])
|
437
|
+
end
|
438
|
+
|
439
|
+
it "should log an error if unsubscribe raises an exception and activate block if provided" do
|
440
|
+
@logger.should_receive(:error).with(/Failed unsubscribing/).once
|
441
|
+
@queue.should_receive(:unsubscribe).and_raise(Exception).once
|
442
|
+
@exceptions.should_receive(:track).once
|
443
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
444
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
445
|
+
called = 0
|
446
|
+
broker.unsubscribe(["queue1"]) { called += 1 }
|
447
|
+
called.should == 1
|
448
|
+
end
|
449
|
+
|
450
|
+
end # when unsubscribing
|
451
|
+
|
452
|
+
context "when declaring" do
|
453
|
+
|
454
|
+
before(:each) do
|
455
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
456
|
+
@channel.should_receive(:queues).and_return({}).by_default
|
457
|
+
@channel.should_receive(:exchanges).and_return({}).by_default
|
458
|
+
end
|
459
|
+
|
460
|
+
it "should declare exchange and return true" do
|
461
|
+
@channel.should_receive(:exchange).once
|
462
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
463
|
+
broker.declare(:exchange, "x", :durable => true).should be_true
|
464
|
+
end
|
465
|
+
|
466
|
+
it "should delete the exchange or queue from the AMQP cache before declaring" do
|
467
|
+
@channel.should_receive(:queue).once
|
468
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
469
|
+
flexmock(broker).should_receive(:delete_amqp_resources).with(:queue, "queue").once
|
470
|
+
broker.declare(:queue, "queue", :durable => true).should be_true
|
471
|
+
end
|
472
|
+
|
473
|
+
it "should log declaration" do
|
474
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
475
|
+
@logger.should_receive(:info).with(/Declaring/).once
|
476
|
+
@channel.should_receive(:queue).once
|
477
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
478
|
+
broker.declare(:queue, "q").should be_true
|
479
|
+
end
|
480
|
+
|
481
|
+
it "should return false if client not usable" do
|
482
|
+
@channel.should_receive(:exchange).never
|
483
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
484
|
+
broker.__send__(:update_status, :disconnected)
|
485
|
+
broker.declare(:exchange, "x", :durable => true).should be_false
|
486
|
+
|
487
|
+
end
|
488
|
+
|
489
|
+
it "should log an error if the declare fails and return false" do
|
490
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
491
|
+
@logger.should_receive(:info).with(/Declaring/).once
|
492
|
+
@logger.should_receive(:error).with(/Failed declaring/).once
|
493
|
+
@exceptions.should_receive(:track).once
|
494
|
+
@channel.should_receive(:queue).and_raise(Exception).once
|
495
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
496
|
+
broker.declare(:queue, "q").should be_false
|
497
|
+
end
|
498
|
+
|
499
|
+
end # when declaring
|
500
|
+
|
501
|
+
context "when publishing" do
|
502
|
+
|
503
|
+
before(:each) do
|
504
|
+
@direct = flexmock("direct")
|
505
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
506
|
+
end
|
507
|
+
|
508
|
+
it "should serialize message, publish it, and return true" do
|
509
|
+
@channel.should_receive(:direct).with("exchange", :durable => true).and_return(@direct).once
|
510
|
+
@direct.should_receive(:publish).with(@message, :persistent => true).once
|
511
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
512
|
+
broker.__send__(:update_status, :ready)
|
513
|
+
broker.publish({:type => :direct, :name => "exchange", :options => {:durable => true}},
|
514
|
+
@packet, @message, :persistent => true).should be_true
|
515
|
+
end
|
516
|
+
|
517
|
+
it "should delete the exchange or queue from the AMQP cache if :declare specified" do
|
518
|
+
@channel.should_receive(:direct).with("exchange", {:declare => true}).and_return(@direct)
|
519
|
+
@direct.should_receive(:publish).with(@message, {})
|
520
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
521
|
+
broker.__send__(:update_status, :ready)
|
522
|
+
exchange = {:type => :direct, :name => "exchange", :options => {:declare => true}}
|
523
|
+
flexmock(broker).should_receive(:delete_amqp_resources).with(:direct, "exchange").once
|
524
|
+
broker.publish(exchange, @packet, @message).should be_true
|
525
|
+
end
|
526
|
+
|
527
|
+
it "should return false if client not connected" do
|
528
|
+
@channel.should_receive(:direct).never
|
529
|
+
@direct.should_receive(:publish).with(@message, :persistent => true).never
|
530
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
531
|
+
broker.publish({:type => :direct, :name => "exchange", :options => {:durable => true}},
|
532
|
+
@packet, @message, :persistent => true).should be_false
|
533
|
+
end
|
534
|
+
|
535
|
+
it "should log an error if the publish fails" do
|
536
|
+
@logger.should_receive(:error).with(/Failed publishing/).once
|
537
|
+
@exceptions.should_receive(:track).once
|
538
|
+
@channel.should_receive(:direct).and_raise(Exception)
|
539
|
+
@direct.should_receive(:publish).with(@message, {}).never
|
540
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
541
|
+
broker.__send__(:update_status, :ready)
|
542
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message).should be_false
|
543
|
+
end
|
544
|
+
|
545
|
+
it "should log that message is being sent with info about which broker used" do
|
546
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
547
|
+
@logger.should_receive(:info).with(/^SEND b0/).once
|
548
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
549
|
+
@direct.should_receive(:publish).with(@message, {}).once
|
550
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
551
|
+
broker.__send__(:update_status, :ready)
|
552
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message).should be_true
|
553
|
+
end
|
554
|
+
|
555
|
+
it "should log broker choices for :debug level" do
|
556
|
+
@logger.should_receive(:level).and_return(:debug)
|
557
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
558
|
+
@logger.should_receive(:info).with(/^SEND b0.*publish options/).once
|
559
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
560
|
+
@direct.should_receive(:publish).with(@message, {}).once
|
561
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
562
|
+
broker.__send__(:update_status, :ready)
|
563
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message).should be_true
|
564
|
+
end
|
565
|
+
|
566
|
+
it "should not log a message if requested not to" do
|
567
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
568
|
+
@logger.should_receive(:info).with(/^SEND/).never
|
569
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
570
|
+
@direct.should_receive(:publish).with(@message, :no_log => true).once
|
571
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
572
|
+
broker.__send__(:update_status, :ready)
|
573
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message, :no_log => true).should be_true
|
574
|
+
end
|
575
|
+
|
576
|
+
it "should not log a message if requested not to unless debug level" do
|
577
|
+
@logger.should_receive(:level).and_return(:debug)
|
578
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
579
|
+
@logger.should_receive(:info).with(/^SEND/).once
|
580
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
581
|
+
@direct.should_receive(:publish).with(@message, :no_log => true).once
|
582
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
583
|
+
broker.__send__(:update_status, :ready)
|
584
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message, :no_log => true).should be_true
|
585
|
+
end
|
586
|
+
|
587
|
+
it "should display broker alias in the log" do
|
588
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
589
|
+
@logger.should_receive(:info).with(/^SEND b0 /).once
|
590
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
591
|
+
@direct.should_receive(:publish).with(@message, {}).once
|
592
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
593
|
+
broker.__send__(:update_status, :ready)
|
594
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message).should be_true
|
595
|
+
end
|
596
|
+
|
597
|
+
it "should filter the packet display for :info level" do
|
598
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
599
|
+
@logger.should_receive(:info).with(/^SEND.*TO YOU/).once
|
600
|
+
@logger.should_receive(:info).with(/^SEND.*TO YOU/).never
|
601
|
+
@packet.should_receive(:to_s).with([:to], :send_version).and_return("TO YOU").once
|
602
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
603
|
+
@direct.should_receive(:publish).with(@message, :log_filter => [:to]).once
|
604
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
605
|
+
broker.__send__(:update_status, :ready)
|
606
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message, :log_filter => [:to]).should be_true
|
607
|
+
end
|
608
|
+
|
609
|
+
it "should not filter the packet display for :debug level" do
|
610
|
+
@logger.should_receive(:level).and_return(:debug)
|
611
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
612
|
+
@logger.should_receive(:info).with(/^SEND.*ALL/).never
|
613
|
+
@logger.should_receive(:info).with(/^SEND.*ALL/).once
|
614
|
+
@packet.should_receive(:to_s).with(nil, :send_version).and_return("ALL").once
|
615
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
616
|
+
@direct.should_receive(:publish).with(@message, :log_filter => [:to]).once
|
617
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
618
|
+
broker.__send__(:update_status, :ready)
|
619
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message, :log_filter => [:to]).should be_true
|
620
|
+
end
|
621
|
+
|
622
|
+
it "should display additional data in log" do
|
623
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
624
|
+
@logger.should_receive(:info).with(/^SEND.*More data/).once
|
625
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
626
|
+
@direct.should_receive(:publish).with(@message, :log_data => "More data").once
|
627
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
628
|
+
broker.__send__(:update_status, :ready)
|
629
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message, :log_data => "More data").should be_true
|
630
|
+
end
|
631
|
+
|
632
|
+
it "should display RE-SEND if the message being sent is a retry" do
|
633
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
634
|
+
@logger.should_receive(:info).with(/^RE-SEND/).once
|
635
|
+
@packet.should_receive(:tries).and_return(["try1"]).once
|
636
|
+
@channel.should_receive(:direct).with("exchange", {}).and_return(@direct).once
|
637
|
+
@direct.should_receive(:publish).with(@message, {}).once
|
638
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
639
|
+
broker.__send__(:update_status, :ready)
|
640
|
+
broker.publish({:type => :direct, :name => "exchange"}, @packet, @message).should be_true
|
641
|
+
end
|
642
|
+
|
643
|
+
end # when publishing
|
644
|
+
|
645
|
+
context "when returning" do
|
646
|
+
|
647
|
+
class MQ
|
648
|
+
attr_accessor :connection, :on_return_message
|
649
|
+
|
650
|
+
def initialize(connection)
|
651
|
+
@connection = connection
|
652
|
+
end
|
653
|
+
|
654
|
+
def return_message(&blk)
|
655
|
+
@on_return_message = blk
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
before(:each) do
|
660
|
+
@info = flexmock("info", :reply_text => "NO_CONSUMERS", :exchange => "exchange", :routing_key => "routing_key").by_default
|
661
|
+
end
|
662
|
+
|
663
|
+
it "should invoke block and log the return" do
|
664
|
+
@logger.should_receive(:info).with(/Connecting to broker/).once
|
665
|
+
@logger.should_receive(:debug).with(/RETURN b0/).once
|
666
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
667
|
+
called = 0
|
668
|
+
broker.return_message do |to, reason, message|
|
669
|
+
called += 1
|
670
|
+
to.should == "exchange"
|
671
|
+
reason.should == "NO_CONSUMERS"
|
672
|
+
message.should == @message
|
673
|
+
end
|
674
|
+
broker.instance_variable_get(:@channel).on_return_message.call(@info, @message)
|
675
|
+
called.should == 1
|
676
|
+
end
|
677
|
+
|
678
|
+
it "should invoke block with routing key if exchange is empty" do
|
679
|
+
@logger.should_receive(:debug)
|
680
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
681
|
+
called = 0
|
682
|
+
broker.return_message do |to, reason, message|
|
683
|
+
called += 1
|
684
|
+
to.should == "routing_key"
|
685
|
+
reason.should == "NO_CONSUMERS"
|
686
|
+
message.should == @message
|
687
|
+
end
|
688
|
+
@info.should_receive(:exchange).and_return("")
|
689
|
+
broker.instance_variable_get(:@channel).on_return_message.call(@info, @message)
|
690
|
+
called.should == 1
|
691
|
+
end
|
692
|
+
|
693
|
+
it "should log an error if there is a failure while processing the return" do
|
694
|
+
@logger.should_receive(:error).with(/Failed return/).once
|
695
|
+
@logger.should_receive(:debug)
|
696
|
+
@exceptions.should_receive(:track).once
|
697
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
698
|
+
called = 0
|
699
|
+
broker.return_message do |to, reason, message|
|
700
|
+
called += 1
|
701
|
+
raise Exception
|
702
|
+
end
|
703
|
+
broker.instance_variable_get(:@channel).on_return_message.call(@info, @message)
|
704
|
+
called.should == 1
|
705
|
+
end
|
706
|
+
|
707
|
+
end # when returning
|
708
|
+
|
709
|
+
context "when deleting" do
|
710
|
+
|
711
|
+
before(:each) do
|
712
|
+
@direct = flexmock("direct")
|
713
|
+
@bind = flexmock("bind", :subscribe => true)
|
714
|
+
@queue = flexmock("queue", :bind => @bind, :name => "queue1")
|
715
|
+
@channel.should_receive(:queue).and_return(@queue).by_default
|
716
|
+
@channel.should_receive(:direct).and_return(@direct).by_default
|
717
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
718
|
+
end
|
719
|
+
|
720
|
+
it "should delete the named queue and return true" do
|
721
|
+
@queue.should_receive(:delete).once
|
722
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
723
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
724
|
+
broker.queues.should == [@queue]
|
725
|
+
broker.delete("queue1").should be_true
|
726
|
+
broker.queues.should == []
|
727
|
+
end
|
728
|
+
|
729
|
+
it "should return false if the client is not usable" do
|
730
|
+
@queue.should_receive(:delete).never
|
731
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
732
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
733
|
+
broker.queues.should == [@queue]
|
734
|
+
broker.__send__(:update_status, :disconnected)
|
735
|
+
broker.delete("queue1").should be_false
|
736
|
+
broker.queues.should == [@queue]
|
737
|
+
end
|
738
|
+
|
739
|
+
it "should log an error and return false if the delete fails" do
|
740
|
+
@logger.should_receive(:error).with(/Failed deleting queue/).once
|
741
|
+
@exceptions.should_receive(:track).once
|
742
|
+
@queue.should_receive(:delete).and_raise(Exception)
|
743
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
744
|
+
broker.subscribe({:name => "queue1"}, {:type => :direct, :name => "exchange"})
|
745
|
+
broker.queues.should == [@queue]
|
746
|
+
broker.delete("queue1").should be_false
|
747
|
+
end
|
748
|
+
|
749
|
+
end # when deleteing
|
750
|
+
|
751
|
+
context "when monitoring" do
|
752
|
+
|
753
|
+
before(:each) do
|
754
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
755
|
+
end
|
756
|
+
|
757
|
+
it "should distinguish whether the client is usable based on whether connecting or connected" do
|
758
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
759
|
+
broker.usable?.should be_true
|
760
|
+
broker.__send__(:update_status, :ready)
|
761
|
+
broker.usable?.should be_true
|
762
|
+
broker.__send__(:update_status, :disconnected)
|
763
|
+
broker.usable?.should be_false
|
764
|
+
@logger.should_receive(:error).with(/Failed to connect to broker b0/).once
|
765
|
+
broker.__send__(:update_status, :failed)
|
766
|
+
broker.usable?.should be_false
|
767
|
+
end
|
768
|
+
|
769
|
+
it "should distinguish whether the client is connected" do
|
770
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
771
|
+
broker.connected?.should be_false
|
772
|
+
broker.__send__(:update_status, :ready)
|
773
|
+
broker.connected?.should be_true
|
774
|
+
broker.__send__(:update_status, :disconnected)
|
775
|
+
broker.connected?.should be_false
|
776
|
+
@logger.should_receive(:error).with(/Failed to connect to broker b0/).once
|
777
|
+
broker.__send__(:update_status, :failed)
|
778
|
+
broker.connected?.should be_false
|
779
|
+
end
|
780
|
+
|
781
|
+
it "should distinguish whether the client has failed" do
|
782
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
783
|
+
broker.failed?.should be_false
|
784
|
+
broker.__send__(:update_status, :ready)
|
785
|
+
broker.failed?.should be_false
|
786
|
+
broker.__send__(:update_status, :disconnected)
|
787
|
+
broker.failed?.should be_false
|
788
|
+
@logger.should_receive(:error).with(/Failed to connect to broker b0/).once
|
789
|
+
broker.__send__(:update_status, :failed)
|
790
|
+
broker.failed?.should be_true
|
791
|
+
end
|
792
|
+
|
793
|
+
it "should give broker summary" do
|
794
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
795
|
+
broker.summary.should == {:alias => "b0", :identity => @identity, :status => :connecting,
|
796
|
+
:disconnects => 0, :failures => 0, :retries => 0}
|
797
|
+
broker.__send__(:update_status, :ready)
|
798
|
+
broker.summary.should == {:alias => "b0", :identity => @identity, :status => :connected,
|
799
|
+
:disconnects => 0, :failures => 0, :retries => 0}
|
800
|
+
@logger.should_receive(:error).with(/Failed to connect to broker/).once
|
801
|
+
broker.__send__(:update_status, :failed)
|
802
|
+
broker.summary.should == {:alias => "b0", :identity => @identity, :status => :failed,
|
803
|
+
:disconnects => 0, :failures => 1, :retries => 0}
|
804
|
+
end
|
805
|
+
|
806
|
+
it "should give broker statistics" do
|
807
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
808
|
+
broker.stats.should == {"alias" => "b0", "identity" => "rs-broker-localhost-5672",
|
809
|
+
"status" => "connecting", "disconnects" => nil, "disconnect last" => nil,
|
810
|
+
"failures" => nil, "failure last" => nil, "retries" => nil}
|
811
|
+
broker.__send__(:update_status, :ready)
|
812
|
+
broker.stats.should == {"alias" => "b0", "identity" => "rs-broker-localhost-5672",
|
813
|
+
"status" => "connected", "disconnects" => nil, "disconnect last" => nil,
|
814
|
+
"failures" => nil, "failure last" => nil, "retries" => nil}
|
815
|
+
@logger.should_receive(:error).with(/Failed to connect to broker/).once
|
816
|
+
broker.__send__(:update_status, :failed)
|
817
|
+
broker.stats.should == {"alias" => "b0", "identity" => "rs-broker-localhost-5672",
|
818
|
+
"status" => "failed", "disconnects" => nil, "disconnect last" => nil,
|
819
|
+
"failures" => 1, "failure last" => {"elapsed" => 0}, "retries" => nil}
|
820
|
+
end
|
821
|
+
|
822
|
+
it "should make update status callback when status changes" do
|
823
|
+
broker = nil
|
824
|
+
called = 0
|
825
|
+
connected_before = false
|
826
|
+
callback = lambda { |b, c| called += 1; b.should == broker; c.should == connected_before }
|
827
|
+
options = {:update_status_callback => callback}
|
828
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, options)
|
829
|
+
broker.__send__(:update_status, :ready)
|
830
|
+
broker.last_failed.should be_false
|
831
|
+
called.should == 1
|
832
|
+
connected_before = true
|
833
|
+
broker.__send__(:update_status, :disconnected)
|
834
|
+
broker.last_failed.should be_false
|
835
|
+
broker.disconnects.total.should == 1
|
836
|
+
called.should == 2
|
837
|
+
broker.__send__(:update_status, :disconnected)
|
838
|
+
broker.disconnects.total.should == 1
|
839
|
+
called.should == 2
|
840
|
+
@logger.should_receive(:error).with(/Failed to connect to broker b0/).once
|
841
|
+
connected_before = false
|
842
|
+
broker.__send__(:update_status, :failed)
|
843
|
+
broker.last_failed.should be_true
|
844
|
+
called.should == 3
|
845
|
+
end
|
846
|
+
|
847
|
+
end # when monitoring
|
848
|
+
|
849
|
+
context "when closing" do
|
850
|
+
|
851
|
+
before(:each) do
|
852
|
+
flexmock(MQ).should_receive(:new).with(@connection).and_return(@channel).by_default
|
853
|
+
end
|
854
|
+
|
855
|
+
it "should close broker connection and send status update" do
|
856
|
+
@connection.should_receive(:close).and_yield.once
|
857
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
858
|
+
flexmock(broker).should_receive(:update_status).once
|
859
|
+
broker.close
|
860
|
+
broker.status.should == :closed
|
861
|
+
end
|
862
|
+
|
863
|
+
it "should not propagate status update if requested not to" do
|
864
|
+
@connection.should_receive(:close).and_yield.once
|
865
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
866
|
+
flexmock(broker).should_receive(:update_status).never
|
867
|
+
broker.close(propagate = false)
|
868
|
+
end
|
869
|
+
|
870
|
+
it "should set status to :failed if not a normal close" do
|
871
|
+
@connection.should_receive(:close).and_yield.once
|
872
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
873
|
+
broker.close(propagate = false, normal = false)
|
874
|
+
broker.status.should == :failed
|
875
|
+
end
|
876
|
+
|
877
|
+
it "should log that closing connection" do
|
878
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
879
|
+
@logger.should_receive(:info).with(/Closed connection to broker b0/).once
|
880
|
+
@connection.should_receive(:close).and_yield.once
|
881
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
882
|
+
broker.close
|
883
|
+
end
|
884
|
+
|
885
|
+
it "should not log if requested not to" do
|
886
|
+
@logger.should_receive(:info).with(/Connecting/).once
|
887
|
+
@logger.should_receive(:info).with(/Closed connection to broker b0/).never
|
888
|
+
@connection.should_receive(:close).and_yield.once
|
889
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
890
|
+
broker.close(propagate = true, normal = true, log = false)
|
891
|
+
end
|
892
|
+
|
893
|
+
it "should close broker connection and execute block if supplied" do
|
894
|
+
@connection.should_receive(:close).and_yield.once
|
895
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
896
|
+
called = 0
|
897
|
+
broker.close { called += 1; broker.status.should == :closed }
|
898
|
+
called.should == 1
|
899
|
+
end
|
900
|
+
|
901
|
+
it "should close broker connection when no block supplied" do
|
902
|
+
@connection.should_receive(:close).and_yield.once
|
903
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
904
|
+
broker.close
|
905
|
+
end
|
906
|
+
|
907
|
+
it "should not propagate status update if already closed" do
|
908
|
+
@connection.should_receive(:close).never
|
909
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
910
|
+
broker.__send__(:update_status, :closed)
|
911
|
+
flexmock(broker).should_receive(:update_status).never
|
912
|
+
broker.close
|
913
|
+
end
|
914
|
+
|
915
|
+
it "should change failed status to closed" do
|
916
|
+
@logger.should_receive(:error).with(/Failed to connect to broker/).once
|
917
|
+
@connection.should_receive(:close).never
|
918
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
919
|
+
broker.__send__(:update_status, :failed)
|
920
|
+
flexmock(broker).should_receive(:update_status).never
|
921
|
+
broker.close
|
922
|
+
broker.status.should == :closed
|
923
|
+
end
|
924
|
+
|
925
|
+
it "should log an error if closing connection fails but still set status to :closed" do
|
926
|
+
@logger.should_receive(:error).with(/Failed to close broker b0/).once
|
927
|
+
@exceptions.should_receive(:track).once
|
928
|
+
@connection.should_receive(:close).and_raise(Exception)
|
929
|
+
broker = RightAMQP::BrokerClient.new(@identity, @address, @serializer, @exceptions, @options)
|
930
|
+
broker.close
|
931
|
+
broker.status.should == :closed
|
932
|
+
end
|
933
|
+
|
934
|
+
end # when closing
|
935
|
+
|
936
|
+
end # RightAMQP::BrokerClient
|