march_hare 2.0.0-java
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.
- 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
|