march_hare 2.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/ext/commons-io.jar +0 -0
- data/lib/ext/rabbitmq-client.jar +0 -0
- data/lib/hot_bunnies.rb +2 -0
- data/lib/march_hare.rb +33 -0
- data/lib/march_hare/channel.rb +952 -0
- data/lib/march_hare/consumers.rb +2 -0
- data/lib/march_hare/consumers/base.rb +121 -0
- data/lib/march_hare/consumers/blocking.rb +73 -0
- data/lib/march_hare/exceptions.rb +174 -0
- data/lib/march_hare/exchange.rb +179 -0
- data/lib/march_hare/juc.rb +9 -0
- data/lib/march_hare/metadata.rb +93 -0
- data/lib/march_hare/queue.rb +265 -0
- data/lib/march_hare/session.rb +440 -0
- data/lib/march_hare/shutdown_listener.rb +15 -0
- data/lib/march_hare/thread_pools.rb +32 -0
- data/lib/march_hare/version.rb +5 -0
- data/lib/march_hare/versioned_delivery_tag.rb +28 -0
- metadata +63 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
require "march_hare/versioned_delivery_tag"
|
2
|
+
|
3
|
+
module MarchHare
|
4
|
+
import com.rabbitmq.client.DefaultConsumer
|
5
|
+
|
6
|
+
class BaseConsumer < DefaultConsumer
|
7
|
+
attr_accessor :consumer_tag
|
8
|
+
attr_accessor :auto_ack
|
9
|
+
|
10
|
+
def initialize(channel, queue, opts)
|
11
|
+
super(channel)
|
12
|
+
@channel = channel
|
13
|
+
@queue = queue
|
14
|
+
@opts = opts
|
15
|
+
@auto_ack = true
|
16
|
+
|
17
|
+
@cancelling = JavaConcurrent::AtomicBoolean.new
|
18
|
+
@cancelled = JavaConcurrent::AtomicBoolean.new
|
19
|
+
|
20
|
+
@terminated = JavaConcurrent::AtomicBoolean.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def handleDelivery(consumer_tag, envelope, properties, bytes)
|
24
|
+
body = String.from_java_bytes(bytes)
|
25
|
+
headers = Headers.new(channel, consumer_tag, envelope, properties)
|
26
|
+
|
27
|
+
deliver(headers, body)
|
28
|
+
end
|
29
|
+
|
30
|
+
def handleCancel(consumer_tag)
|
31
|
+
@cancelled.set(true)
|
32
|
+
@channel.unregister_consumer(consumer_tag)
|
33
|
+
|
34
|
+
if f = @opts[:on_cancellation]
|
35
|
+
case f.arity
|
36
|
+
when 0 then
|
37
|
+
f.call
|
38
|
+
when 1 then
|
39
|
+
f.call(self)
|
40
|
+
when 2 then
|
41
|
+
f.call(@channel, self)
|
42
|
+
when 3 then
|
43
|
+
f.call(@channel, self, consumer_tag)
|
44
|
+
else
|
45
|
+
f.call(@channel, self, consumer_tag)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
@terminated.set(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
def handleCancelOk(consumer_tag)
|
53
|
+
@cancelled.set(true)
|
54
|
+
@channel.unregister_consumer(consumer_tag)
|
55
|
+
|
56
|
+
@terminated.set(true)
|
57
|
+
end
|
58
|
+
|
59
|
+
def start
|
60
|
+
# no-op
|
61
|
+
end
|
62
|
+
|
63
|
+
def gracefully_shut_down
|
64
|
+
# no-op
|
65
|
+
end
|
66
|
+
|
67
|
+
def deliver(headers, message)
|
68
|
+
raise NotImplementedError, 'To be implemented by a subclass'
|
69
|
+
end
|
70
|
+
|
71
|
+
def cancelled?
|
72
|
+
@cancelling.get || @cancelled.get
|
73
|
+
end
|
74
|
+
|
75
|
+
def active?
|
76
|
+
!terminated?
|
77
|
+
end
|
78
|
+
|
79
|
+
def terminated?
|
80
|
+
@terminated.get
|
81
|
+
end
|
82
|
+
|
83
|
+
# @private
|
84
|
+
def recover_from_network_failure
|
85
|
+
@terminated.set(false)
|
86
|
+
@cancelled.set(false)
|
87
|
+
@consumer_tag = @channel.basic_consume(@queue.name, @auto_ack, self)
|
88
|
+
|
89
|
+
@consumer_tag
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class CallbackConsumer < BaseConsumer
|
94
|
+
def initialize(channel, queue, opts, callback)
|
95
|
+
raise ArgumentError, "callback must not be nil!" if callback.nil?
|
96
|
+
|
97
|
+
super(channel, queue, opts)
|
98
|
+
@callback = callback
|
99
|
+
@callback_arity = @callback.arity
|
100
|
+
end
|
101
|
+
|
102
|
+
def deliver(headers, message)
|
103
|
+
if @callback_arity == 2
|
104
|
+
@callback.call(headers, message)
|
105
|
+
else
|
106
|
+
@callback.call(message)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def cancel
|
111
|
+
if @cancelling.get_and_set(true)
|
112
|
+
false
|
113
|
+
else
|
114
|
+
@channel.basic_cancel(@consumer_tag)
|
115
|
+
@cancelled.set(true)
|
116
|
+
@terminated.set(true)
|
117
|
+
true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "march_hare/consumers/base"
|
2
|
+
|
3
|
+
module MarchHare
|
4
|
+
class BlockingCallbackConsumer < CallbackConsumer
|
5
|
+
POISON = :__poison__
|
6
|
+
|
7
|
+
def initialize(channel, queue, buffer_size, opts, callback)
|
8
|
+
super(channel, queue, opts, callback)
|
9
|
+
if buffer_size
|
10
|
+
@internal_queue = JavaConcurrent::ArrayBlockingQueue.new(buffer_size)
|
11
|
+
else
|
12
|
+
@internal_queue = JavaConcurrent::LinkedBlockingQueue.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def cancel
|
17
|
+
if super
|
18
|
+
@internal_queue.offer(POISON)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def start
|
23
|
+
interrupted = false
|
24
|
+
until (@cancelling.get || @cancelled.get) || JavaConcurrent::Thread.current_thread.interrupted?
|
25
|
+
begin
|
26
|
+
pair = @internal_queue.take
|
27
|
+
if pair
|
28
|
+
if pair == POISON
|
29
|
+
@cancelling.set(true)
|
30
|
+
else
|
31
|
+
@callback.call(*pair)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
rescue JavaConcurrent::InterruptedException => e
|
35
|
+
interrupted = true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
while (pair = @internal_queue.poll)
|
39
|
+
if pair
|
40
|
+
if pair == POISON
|
41
|
+
@cancelling.set(true)
|
42
|
+
else
|
43
|
+
@callback.call(*pair)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@terminated.set(true)
|
48
|
+
if interrupted
|
49
|
+
JavaConcurrent::Thread.current_thread.interrupt
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def deliver(*pair)
|
54
|
+
if (@cancelling.get || @cancelled.get) || JavaConcurrent::Thread.current_thread.interrupted?
|
55
|
+
@internal_queue.offer(pair)
|
56
|
+
else
|
57
|
+
begin
|
58
|
+
@internal_queue.put(pair)
|
59
|
+
rescue JavaConcurrent::InterruptedException => e
|
60
|
+
JavaConcurrent::Thread.current_thread.interrupt
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def gracefully_shut_down
|
66
|
+
@cancelling.set(true)
|
67
|
+
@internal_queue.offer(POISON)
|
68
|
+
|
69
|
+
@terminated.set(true)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module MarchHare
|
2
|
+
class Exception < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class ShutdownSignal < Exception
|
6
|
+
attr_reader :cause
|
7
|
+
|
8
|
+
def initialize(cause)
|
9
|
+
@cause = cause
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class NetworkException < Exception
|
14
|
+
end
|
15
|
+
|
16
|
+
class ConnectionRefused < NetworkException
|
17
|
+
end
|
18
|
+
|
19
|
+
class ChannelLevelException < Exception
|
20
|
+
attr_reader :channel_close
|
21
|
+
|
22
|
+
def initialize(message, channel_close)
|
23
|
+
super(message)
|
24
|
+
|
25
|
+
@channel_close = channel_close
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ConnectionLevelException < Exception
|
30
|
+
attr_reader :connection_close
|
31
|
+
|
32
|
+
def initialize(message, connection_close)
|
33
|
+
super(message)
|
34
|
+
|
35
|
+
@connection_close = connection_close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Raised when RabbitMQ closes network connection before
|
40
|
+
# finalizing the connection, typically indicating authentication failure.
|
41
|
+
#
|
42
|
+
# RabbitMQ versions beyond 3.2 use a better defined authentication failure
|
43
|
+
# notifications.
|
44
|
+
class PossibleAuthenticationFailureError < Exception
|
45
|
+
attr_reader :username, :vhost
|
46
|
+
|
47
|
+
def initialize(username, vhost, password_length)
|
48
|
+
@username = username
|
49
|
+
@vhost = vhost
|
50
|
+
|
51
|
+
super("Authentication with RabbitMQ failed or RabbitMQ version used does not support AMQP 0-9-1. Username: #{username}, vhost: #{vhost}, password length: #{password_length}. Please check your configuration.")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Raised when RabbitMQ 3.2+ reports authentication
|
56
|
+
# failure before closing TCP connection.
|
57
|
+
class AuthenticationFailureError < PossibleAuthenticationFailureError
|
58
|
+
attr_reader :username, :vhost
|
59
|
+
|
60
|
+
def initialize(username, vhost, password_length)
|
61
|
+
super(username, vhost, password_length)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class PreconditionFailed < ChannelLevelException
|
66
|
+
end
|
67
|
+
|
68
|
+
class NotFound < ChannelLevelException
|
69
|
+
end
|
70
|
+
|
71
|
+
class ResourceLocked < ChannelLevelException
|
72
|
+
end
|
73
|
+
|
74
|
+
class AccessRefused < ChannelLevelException
|
75
|
+
end
|
76
|
+
|
77
|
+
class ChannelError < ConnectionLevelException
|
78
|
+
end
|
79
|
+
|
80
|
+
class InvalidCommand < ConnectionLevelException
|
81
|
+
end
|
82
|
+
|
83
|
+
class FrameError < ConnectionLevelException
|
84
|
+
end
|
85
|
+
|
86
|
+
class UnexpectedFrame < ConnectionLevelException
|
87
|
+
end
|
88
|
+
|
89
|
+
class ChannelAlreadyClosed < Exception
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
# Converts RabbitMQ Java client exceptions
|
95
|
+
#
|
96
|
+
# @private
|
97
|
+
class Exceptions
|
98
|
+
def self.convert(e, unwrap_io_exception = true)
|
99
|
+
case e
|
100
|
+
when java.io.IOException then
|
101
|
+
c = e.cause
|
102
|
+
|
103
|
+
if unwrap_io_exception
|
104
|
+
convert(c, false)
|
105
|
+
else
|
106
|
+
c
|
107
|
+
end
|
108
|
+
when com.rabbitmq.client.AlreadyClosedException then
|
109
|
+
ChannelAlreadyClosed.new(e.reason)
|
110
|
+
when com.rabbitmq.client.ShutdownSignalException then
|
111
|
+
cmd = e.reason
|
112
|
+
|
113
|
+
exception_for_protocol_method(cmd.method)
|
114
|
+
else
|
115
|
+
e
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.convert_and_reraise(e)
|
120
|
+
raise convert(e)
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.exception_for_protocol_method(m)
|
124
|
+
case m
|
125
|
+
# com.rabbitmq.client.AMQP.Connection.Close does not resolve the inner
|
126
|
+
# class correctly. Looks like a JRuby bug we work around by using Rubyesque
|
127
|
+
# class name. MK.
|
128
|
+
when Java::ComRabbitmqClient::AMQP::Connection::Close then
|
129
|
+
exception_for_connection_close(m)
|
130
|
+
when Java::ComRabbitmqClient::AMQP::Channel::Close then
|
131
|
+
exception_for_channel_close(m)
|
132
|
+
else
|
133
|
+
NotImplementedError.new("Exception convertion for protocol method #{m.inspect} is not implemented!")
|
134
|
+
end
|
135
|
+
end # def self
|
136
|
+
|
137
|
+
|
138
|
+
def self.exception_for_connection_close(m)
|
139
|
+
klass = case m.reply_code
|
140
|
+
when 320 then
|
141
|
+
ConnectionForced
|
142
|
+
when 501 then
|
143
|
+
FrameError
|
144
|
+
when 503 then
|
145
|
+
InvalidCommand
|
146
|
+
when 504 then
|
147
|
+
ChannelError
|
148
|
+
when 505 then
|
149
|
+
UnexpectedFrame
|
150
|
+
else
|
151
|
+
raise "Unknown reply code: #{m.reply_code}, text: #{m.reply_text}"
|
152
|
+
end
|
153
|
+
|
154
|
+
klass.new("Connection-level error: #{m.reply_text}", m)
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.exception_for_channel_close(m)
|
158
|
+
klass = case m.reply_code
|
159
|
+
when 403 then
|
160
|
+
AccessRefused
|
161
|
+
when 404 then
|
162
|
+
NotFound
|
163
|
+
when 405 then
|
164
|
+
ResourceLocked
|
165
|
+
when 406 then
|
166
|
+
PreconditionFailed
|
167
|
+
else
|
168
|
+
ChannelLevelException
|
169
|
+
end
|
170
|
+
|
171
|
+
klass.new(m.reply_text, m)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end # MarchHare
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module MarchHare
|
4
|
+
import com.rabbitmq.client.AMQP
|
5
|
+
|
6
|
+
# Represents AMQP 0.9.1 exchanges.
|
7
|
+
#
|
8
|
+
# @see http://rubymarchhare.info/articles/exchanges.html Exchanges and Publishing guide
|
9
|
+
# @see http://rubymarchhare.info/articles/extensions.html RabbitMQ Extensions guide
|
10
|
+
# @see Queue#bind
|
11
|
+
class Exchange
|
12
|
+
# @return [String] Exchange name
|
13
|
+
attr_reader :name
|
14
|
+
# @return [MarchHare::Channel] Channel this exchange object uses
|
15
|
+
attr_reader :channel
|
16
|
+
|
17
|
+
# Type of this exchange (one of: :direct, :fanout, :topic, :headers).
|
18
|
+
# @return [Symbol]
|
19
|
+
attr_reader :type
|
20
|
+
|
21
|
+
# Instantiates a new exchange.
|
22
|
+
#
|
23
|
+
# @param [Channel] channel Channel to declare exchange on
|
24
|
+
# @params [String] name Exchange name
|
25
|
+
# @params [Hash] options ({}) Exchange and declaration attributes
|
26
|
+
#
|
27
|
+
# @options opts :type [Symbol, String] Exchange type
|
28
|
+
# @options opts :durable [Boolean] (false) Will the exchange be durable?
|
29
|
+
# @options opts :auto_delete [Boolean] (false) Will the exchange be auto-deleted?
|
30
|
+
# @options opts :passive [Boolean] (false) Should passive declaration be used?
|
31
|
+
#
|
32
|
+
# @see MarchHare::Channel#default_exchange
|
33
|
+
# @see MarchHare::Channel#fanout
|
34
|
+
# @see MarchHare::Channel#topic
|
35
|
+
# @see MarchHare::Channel#direct
|
36
|
+
# @see MarchHare::Channel#headers
|
37
|
+
# @see MarchHare::Channel#exchange
|
38
|
+
def initialize(channel, name, options = {})
|
39
|
+
raise ArgumentError, "exchange channel cannot be nil" if channel.nil?
|
40
|
+
raise ArgumentError, "exchange name cannot be nil" if name.nil?
|
41
|
+
raise ArgumentError, "exchange :type must be specified as an option" if options[:type].nil?
|
42
|
+
|
43
|
+
@channel = channel
|
44
|
+
@name = name
|
45
|
+
@type = options[:type]
|
46
|
+
@options = {:type => :fanout, :durable => false, :auto_delete => false, :internal => false, :passive => false}.merge(options)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Publishes a message
|
50
|
+
#
|
51
|
+
# @param [String] payload Message payload. It will never be modified by MarchHare or RabbitMQ in any way.
|
52
|
+
# @param [Hash] opts Message properties (metadata) and delivery settings
|
53
|
+
#
|
54
|
+
# @option opts [String] :routing_key Routing key
|
55
|
+
# @option opts [Boolean] :persistent Should the message be persisted to disk?
|
56
|
+
# @option opts [Boolean] :mandatory Should the message be returned if it cannot be routed to any queue?
|
57
|
+
# @option opts [Hash] :properties Messages and delivery properties
|
58
|
+
#
|
59
|
+
# * :timestamp (Integer) A timestamp associated with this message
|
60
|
+
# * :expiration (Integer) Expiration time after which the message will be deleted
|
61
|
+
# * :type (String) Message type, e.g. what type of event or command this message represents. Can be any string
|
62
|
+
# * :reply_to (String) Queue name other apps should send the response to
|
63
|
+
# * :content_type (String) Message content type (e.g. application/json)
|
64
|
+
# * :content_encoding (String) Message content encoding (e.g. gzip)
|
65
|
+
# * :correlation_id (String) Message correlated to this one, e.g. what request this message is a reply for
|
66
|
+
# * :priority (Integer) Message priority, 0 to 9. Not used by RabbitMQ, only applications
|
67
|
+
# * :message_id (String) Any message identifier
|
68
|
+
# * :user_id (String) Optional user ID. Verified by RabbitMQ against the actual connection username
|
69
|
+
# * :app_id (String) Optional application ID
|
70
|
+
#
|
71
|
+
# @return [MarchHare::Exchange] Self
|
72
|
+
# @see http://rubymarchhare.info/articles/exchanges.html Exchanges and Publishing guide
|
73
|
+
# @api public
|
74
|
+
def publish(body, opts = {})
|
75
|
+
options = {:routing_key => '', :mandatory => false}.merge(opts)
|
76
|
+
@channel.basic_publish(@name,
|
77
|
+
options[:routing_key],
|
78
|
+
options[:mandatory],
|
79
|
+
options.fetch(:properties, Hash.new),
|
80
|
+
body.to_java_bytes)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Deletes the exchange unless it is predefined
|
84
|
+
#
|
85
|
+
# @param [Hash] options Options
|
86
|
+
#
|
87
|
+
# @option opts [Boolean] if_unused (false) Should this exchange be deleted only if it is no longer used
|
88
|
+
#
|
89
|
+
# @see http://rubymarchhare.info/articles/exchanges.html Exchanges and Publishing guide
|
90
|
+
# @api public
|
91
|
+
def delete(options={})
|
92
|
+
@channel.deregister_exchange(self)
|
93
|
+
@channel.exchange_delete(@name, options.fetch(:if_unused, false)) unless predefined?
|
94
|
+
end
|
95
|
+
|
96
|
+
# Binds an exchange to another (source) exchange using exchange.bind AMQP 0.9.1 extension
|
97
|
+
# that RabbitMQ provides.
|
98
|
+
#
|
99
|
+
# @param [String] exchange Source exchange name
|
100
|
+
# @param [Hash] options Options
|
101
|
+
#
|
102
|
+
# @option opts [String] routing_key (nil) Routing key used for binding
|
103
|
+
# @option opts [Hash] arguments ({}) Optional arguments
|
104
|
+
#
|
105
|
+
# @return [MarchHare::Exchange] Self
|
106
|
+
# @see http://rubymarchhare.info/articles/exchanges.html Exchanges and Publishing guide
|
107
|
+
# @see http://rubymarchhare.info/articles/bindings.html Bindings guide
|
108
|
+
# @see http://rubymarchhare.info/articles/extensions.html RabbitMQ Extensions guide
|
109
|
+
# @api public
|
110
|
+
def bind(exchange, options={})
|
111
|
+
exchange_name = if exchange.respond_to?(:name) then exchange.name else exchange.to_s end
|
112
|
+
@channel.exchange_bind(@name, exchange_name, options.fetch(:routing_key, ''))
|
113
|
+
end
|
114
|
+
|
115
|
+
# Unbinds an exchange from another (source) exchange using exchange.unbind AMQP 0.9.1 extension
|
116
|
+
# that RabbitMQ provides.
|
117
|
+
#
|
118
|
+
# @param [String] source Source exchange name
|
119
|
+
# @param [Hash] opts Options
|
120
|
+
#
|
121
|
+
# @option opts [String] routing_key (nil) Routing key used for binding
|
122
|
+
# @option opts [Hash] arguments ({}) Optional arguments
|
123
|
+
#
|
124
|
+
# @return [Bunny::Exchange] Self
|
125
|
+
# @see http://rubymarchhare.info/articles/exchanges.html Exchanges and Publishing guide
|
126
|
+
# @see http://rubymarchhare.info/articles/bindings.html Bindings guide
|
127
|
+
# @see http://rubymarchhare.info/articles/extensions.html RabbitMQ Extensions guide
|
128
|
+
# @api public
|
129
|
+
def unbind(exchange, opts = {})
|
130
|
+
exchange_name = if exchange.respond_to?(:name) then exchange.name else exchange.to_s end
|
131
|
+
@channel.exchange_unbind(@name, exchange_name, opts.fetch(:routing_key, ''), opts[:arguments])
|
132
|
+
end
|
133
|
+
|
134
|
+
# @return [Boolean] true if this exchange is a pre-defined one (amq.direct, amq.fanout, amq.match and so on)
|
135
|
+
def predefined?
|
136
|
+
@name.empty? || @name.start_with?("amq.")
|
137
|
+
end
|
138
|
+
|
139
|
+
# Waits until all outstanding publisher confirms on the channel
|
140
|
+
# arrive.
|
141
|
+
#
|
142
|
+
# This is a convenience method that delegates to {Channel#wait_for_confirms}
|
143
|
+
#
|
144
|
+
# @api public
|
145
|
+
def wait_for_confirms
|
146
|
+
@channel.wait_for_confirms
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
#
|
151
|
+
# Implementation
|
152
|
+
#
|
153
|
+
|
154
|
+
# @private
|
155
|
+
def declare!
|
156
|
+
unless predefined?
|
157
|
+
if @options[:passive]
|
158
|
+
then @channel.exchange_declare_passive(@name)
|
159
|
+
else @channel.exchange_declare(@name, @options[:type].to_s, @options[:durable], @options[:auto_delete], @options[:arguments])
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# @private
|
165
|
+
def recover_from_network_failure
|
166
|
+
# puts "Recovering exchange #{@name} from network failure"
|
167
|
+
unless predefined?
|
168
|
+
begin
|
169
|
+
declare!
|
170
|
+
|
171
|
+
@channel.register_exchange(self)
|
172
|
+
rescue Exception => e
|
173
|
+
# TODO: use a logger
|
174
|
+
puts "Caught #{e.inspect} while redeclaring and registering exchange #{@name}!"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|