march_hare 3.1.1-java → 4.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 910cb519cfde61ec8390a0c56db3121eb8e5675a3c5b19d662db8ad9a3f7a8d7
4
- data.tar.gz: 0be92a42c7ea2102c442184d0cc892fb171a83f59a718fc1411514f51b5c4dae
3
+ metadata.gz: 006ea49a052e4f2995f87e2739eacfd552945f61135ba8b329cd8dcdf36ede45
4
+ data.tar.gz: 5ef91217f326fb9cca331378adaae5684a4e98d0b70748b4fd04227c95ccfc74
5
5
  SHA512:
6
- metadata.gz: 2224b9d612f2419772a19cee956a433243b9e76a3807c372cca723591ee338ab9a2dfa9353e7bbe25601337189b9ab5468ffde8217e7142442baee97b66f082c
7
- data.tar.gz: f592e103fcb40342e7162cbb9a10808267eeb435b017438ebf9590745684903018ddd1a5aad6d0f80ca4d59b1a85b6b34bfe18c0fe716b2eb0ef2b12843c4d40
6
+ metadata.gz: 121e50ac297e48dd61a08f6b08a81e85782bf6dfe402d48320f2654daa4f3cfbbfc3a76c69a61114a7add12ccbe771bcfd7115b4c47cba65fb13cc4bebc32b70
7
+ data.tar.gz: 2fcaa00100551f6d6a3fd4005722e168684598c612279668f5c82e324848156722d69e2b86a3a7f2efb5cbabeae8de19546ea94ddb5bfa0a9167e594bbaabf2d
Binary file
Binary file
Binary file
@@ -144,6 +144,11 @@ module MarchHare
144
144
  alias client session
145
145
  alias connection session
146
146
 
147
+ # @return [::Logger] Logger instance from the connection
148
+ def logger
149
+ @connection.logger
150
+ end
151
+
147
152
  # @return [Integer] Channel id
148
153
  def channel_number
149
154
  @delegate.channel_number
@@ -187,6 +192,8 @@ module MarchHare
187
192
 
188
193
  # @private
189
194
  def automatically_recover(session, java_connection)
195
+ logger.debug("channel: begin automatic connection recovery")
196
+
190
197
  jch = java_connection.create_channel(id)
191
198
 
192
199
  self.revive_with(jch)
@@ -247,10 +254,11 @@ module MarchHare
247
254
  def recover_exchanges
248
255
  @exchanges.values.each do |x|
249
256
  begin
257
+ logger.debug("channel: recover exchange #{x.name}")
250
258
  x.recover_from_network_failure
251
259
  rescue Exception => e
252
- # TODO: logger
253
- $stderr.puts "Caught exception when recovering exchange #{x.name}"
260
+ logger.error("Caught exception when recovering exchange #{x.name}")
261
+ logger.error(e)
254
262
  end
255
263
  end
256
264
  end
@@ -260,10 +268,11 @@ module MarchHare
260
268
  def recover_queues
261
269
  @queues.values.each do |q|
262
270
  begin
271
+ logger.debug("channel: recover queue #{q.name}")
263
272
  q.recover_from_network_failure
264
273
  rescue Exception => e
265
- # TODO: logger
266
- $stderr.puts "Caught exception when recovering queue #{q.name}"
274
+ logger.error("Caught exception when recovering queue #{q.name}")
275
+ logger.error(e)
267
276
  end
268
277
  end
269
278
  end
@@ -273,11 +282,12 @@ module MarchHare
273
282
  def recover_consumers
274
283
  @consumers.values.each do |c|
275
284
  begin
285
+ logger.debug("channel: recover consumer #{c.consumer_tag}")
276
286
  self.unregister_consumer(c.consumer_tag)
277
287
  c.recover_from_network_failure
278
288
  rescue Exception => e
279
- # TODO: logger
280
- $stderr.puts "Caught exception when recovering consumer #{c.consumer_tag}"
289
+ logger.error("Caught exception when recovering consumer #{c.consumer_tag}")
290
+ logger.error(e)
281
291
  end
282
292
  end
283
293
  end
@@ -924,6 +934,7 @@ module MarchHare
924
934
 
925
935
  # @private
926
936
  def deregister_queue(queue)
937
+ logger.debug("channel: deregister queue #{queue.name}")
927
938
  @queues.delete(queue.name)
928
939
  end
929
940
 
@@ -934,6 +945,7 @@ module MarchHare
934
945
 
935
946
  # @private
936
947
  def register_queue(queue)
948
+ logger.debug("channel: register queue #{queue.name}")
937
949
  @queues[queue.name] = queue
938
950
  end
939
951
 
@@ -944,21 +956,25 @@ module MarchHare
944
956
 
945
957
  # @private
946
958
  def deregister_exchange(exchange)
959
+ logger.debug("channel: deregister exchange #{exchange.name}")
947
960
  @exchanges.delete(exchange.name)
948
961
  end
949
962
 
950
963
  # @private
951
964
  def register_exchange(exchange)
965
+ logger.debug("channel: register exchange #{exchange.name}")
952
966
  @exchanges[exchange.name] = exchange
953
967
  end
954
968
 
955
969
  # @private
956
970
  def register_consumer(consumer_tag, consumer)
971
+ logger.debug("channel: register consumer #{consumer_tag}")
957
972
  @consumers[consumer_tag] = consumer
958
973
  end
959
974
 
960
975
  # @private
961
976
  def unregister_consumer(consumer_tag)
977
+ logger.debug("channel: unregister consumer #{consumer_tag}")
962
978
  @consumers.delete(consumer_tag)
963
979
  end
964
980
 
@@ -0,0 +1,17 @@
1
+ module MarchHare
2
+ class ExceptionHandler < com.rabbitmq.client.impl.ForgivingExceptionHandler
3
+ def initialize(logger)
4
+ super()
5
+ @logger = logger
6
+ end
7
+
8
+ def log(msg, error)
9
+ logger.error(msg)
10
+ logger.error(error)
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :logger
16
+ end
17
+ end
@@ -16,6 +16,12 @@ module MarchHare
16
16
  class ConnectionRefused < NetworkException
17
17
  end
18
18
 
19
+ class ConnectionClosedException < Exception
20
+ def initialize(message='')
21
+ super("Connection was explicitly closed and cannot be reopened. Create a new Connection instead. #{message}")
22
+ end
23
+ end
24
+
19
25
  class ChannelLevelException < Exception
20
26
  attr_reader :channel_close
21
27
 
@@ -99,14 +105,14 @@ module MarchHare
99
105
  def self.convert(e, unwrap_io_exception = true)
100
106
  case e
101
107
  when java.net.SocketException then
102
- IOError.new
108
+ IOError.new(e.message)
103
109
  when java.io.IOException then
104
110
  c = e.cause
105
111
 
106
112
  if c && unwrap_io_exception
107
113
  convert(c, false)
108
114
  else
109
- IOError.new
115
+ IOError.new(e.message)
110
116
  end
111
117
  when com.rabbitmq.client.AlreadyClosedException then
112
118
  ChannelAlreadyClosed.new(e.reason)
@@ -193,8 +193,8 @@ module MarchHare
193
193
 
194
194
  @channel.register_exchange(self)
195
195
  rescue Exception => e
196
- # TODO: use a logger
197
- puts "Caught #{e.inspect} while redeclaring and registering exchange #{@name}!"
196
+ @channel.logger.error("Caught Exception while redeclaring and registering exchange #{@name}!")
197
+ @channel.logger.error(e)
198
198
  end
199
199
  end
200
200
  end
@@ -168,7 +168,6 @@ module MarchHare
168
168
  #
169
169
  # @option opts [Boolean] :manual_ack (false) Will this consumer use manual acknowledgements?
170
170
  # @option opts [Boolean] :exclusive (false) Should this consumer be exclusive for this queue?
171
- # @option opts [Boolean] :block (false) Should the call block calling thread?
172
171
  # @option opts [#call] :on_cancellation Block to execute when this consumer is cancelled remotely (e.g. via the RabbitMQ Management plugin)
173
172
  # @option opts [String] :consumer_tag Unique consumer identifier. It is usually recommended to let MarchHare generate it for you.
174
173
  # @option opts [Hash] :arguments ({}) Additional (optional) arguments, typically used by RabbitMQ extensions
@@ -233,6 +232,7 @@ module MarchHare
233
232
 
234
233
  # @private
235
234
  def declare!
235
+ @channel.logger.debug("queue: declare! #{@name}")
236
236
  response = if @options[:passive]
237
237
  then @channel.queue_declare_passive(@name)
238
238
  else @channel.queue_declare(@name, @options[:durable], @options[:exclusive], @options[:auto_delete], @options[:arguments])
@@ -258,8 +258,7 @@ module MarchHare
258
258
  # @private
259
259
  def recover_bindings
260
260
  @bindings.each do |b|
261
- # TODO: use a logger
262
- # puts "Recovering binding #{b.inspect}"
261
+ @channel.logger.debug("Recovering binding #{b.inspect}")
263
262
  self.bind(b[:exchange], b)
264
263
  end
265
264
  end
@@ -2,13 +2,15 @@
2
2
  require "march_hare/shutdown_listener"
3
3
  require "set"
4
4
  require "march_hare/thread_pools"
5
+ require "march_hare/exception_handler"
5
6
  require "java"
7
+ require "logger"
6
8
 
7
9
  module MarchHare
8
10
  java_import com.rabbitmq.client.ConnectionFactory
9
11
  java_import com.rabbitmq.client.Connection
10
12
  java_import com.rabbitmq.client.BlockedListener
11
- java_import com.rabbitmq.client.NullTrustManager
13
+ java_import com.rabbitmq.client.TrustEverythingTrustManager
12
14
  java_import com.rabbitmq.client.MissedHeartbeatException
13
15
  java_import com.rabbitmq.client.Address
14
16
 
@@ -52,6 +54,9 @@ module MarchHare
52
54
  # This will switch port to 5671 by default.
53
55
  # @option options [String] :tls_certificate_path Path to a PKCS12 certificate.
54
56
  # @option options [java.util.concurrent.ThreadFactory] :thread_factory Thread factory RabbitMQ Java client will use (useful in restricted PaaS platforms such as GAE)
57
+ # @option options [Logger] :logger The logger. If missing, one is created using :log_file and :log_level.
58
+ # @option options [IO, String] :log_file The file or path to use when creating a logger. Defaults to STDOUT.
59
+ # @option options [Integer] :log_level The log level to use when creating a logger. Defaults to LOGGER::WARN
55
60
  #
56
61
  # @see http://rubymarchhare.info/articles/connecting.html Connecting to RabbitMQ guide
57
62
  def self.connect(options = {})
@@ -77,17 +82,16 @@ module MarchHare
77
82
  cf.connection_timeout = connection_timeout_from(options) if include_connection_timeout?(options)
78
83
 
79
84
  cf.thread_factory = thread_factory_from(options) if include_thread_factory?(options)
80
- cf.exception_handler = exception_handler_from(options) if include_exception_handler?(options)
81
85
 
82
86
  tls = (options[:ssl] || options[:tls])
83
87
  case tls
84
88
  when true then
85
89
  cf.use_ssl_protocol
86
- when String then
87
- # TODO: logging
88
- $stdout.puts "Using TLS/SSL version #{tls}"
89
- # Note: `options[:trust_manager] = com.rabbitmq.client.NullTrustManager.new` can be set to disable TLS verification.
90
- if (cert_path = tls_certificate_path_from(options)) && (password = tls_certificate_password_from(options))
90
+ when String then
91
+ options[:logger].info("Using TLS/SSL version #{tls}") if options[:logger]
92
+ # Note: `options[:trust_manager] = com.rabbitmq.client.TrustEverythingTrustManager.new`
93
+ # can be set to effectively disable TLS verification.
94
+ if (cert_path = tls_certificate_path_from(options)) && (password = tls_certificate_password_from(options))
91
95
  ctx = SSLContext.get_instance(tls)
92
96
  pwd = password.to_java.to_char_array
93
97
  begin
@@ -99,7 +103,7 @@ module MarchHare
99
103
  kmf.init(ks, pwd)
100
104
 
101
105
  if options[:trust_manager]
102
- ctx.init(kmf.get_key_managers, [options[:trust_manager]], nil)
106
+ ctx.init(kmf.get_key_managers, Array(options[:trust_manager]), nil)
103
107
  else
104
108
  # use the key store as the trust store
105
109
  tmf = TrustManagerFactory.get_instance(TrustManagerFactory.getDefaultAlgorithm());
@@ -107,6 +111,7 @@ module MarchHare
107
111
  ctx.init(kmf.get_key_managers, tmf.getTrustManagers(), nil)
108
112
  end
109
113
 
114
+ cf.set_sasl_config(options[:sasl_config]) if options[:sasl_config]
110
115
  cf.use_ssl_protocol(ctx)
111
116
  rescue Java::JavaLang::Throwable => e
112
117
  message = e.message
@@ -134,11 +139,19 @@ module MarchHare
134
139
  # @return [Array<MarchHare::Channel>] Channels opened on this connection
135
140
  attr_reader :channels
136
141
 
142
+ # @return [::Logger] Logger instance
143
+ attr_reader :logger
144
+
137
145
 
138
146
  # @private
139
147
  def initialize(connection_factory, opts = {})
140
148
  @cf = connection_factory
141
149
 
150
+ log_file = opts[:log_file] || STDOUT
151
+ log_level = opts[:log_level] || ENV["MARCH_HARE_LOG_LEVEL"] || Logger::WARN
152
+ @logger = opts.fetch(:logger, init_default_logger(log_file, log_level))
153
+ @cf.exception_handler = opts.fetch(:exception_handler, init_default_exception_handler(@logger))
154
+
142
155
  # March Hare uses its own connection recovery implementation and
143
156
  # as of Java client 4.x automatic recovery is enabled by
144
157
  # default. MK.
@@ -153,7 +166,7 @@ module MarchHare
153
166
  # we expect this option to be specified in seconds
154
167
  @executor_shutdown_timeout = opts.fetch(:executor_shutdown_timeout, 30.0)
155
168
 
156
- @addresses = self.class.adresses_from(opts)
169
+ @addresses = self.class.addresses_from(opts)
157
170
  @connection = build_new_connection
158
171
  @channels = JavaConcurrent::ConcurrentHashMap.new
159
172
 
@@ -165,6 +178,9 @@ module MarchHare
165
178
  end
166
179
  @network_recovery_interval = opts.fetch(:network_recovery_interval, DEFAULT_NETWORK_RECOVERY_INTERVAL)
167
180
  @shutdown_hooks = Array.new
181
+ @blocked_connection_hooks = Array.new
182
+ @connection_recovery_hooks = Array.new
183
+ @was_explicitly_closed = false
168
184
 
169
185
  if @automatically_recover
170
186
  self.add_automatic_recovery_hook
@@ -210,8 +226,16 @@ module MarchHare
210
226
  ch.close
211
227
  end
212
228
 
229
+ @was_explicitly_closed = true
213
230
  maybe_shut_down_executor
214
231
  @connection.close
232
+ rescue com.rabbitmq.client.AlreadyClosedException
233
+ @logger.debug("close: connection already closed")
234
+ end
235
+
236
+ def reopen
237
+ @was_explicitly_closed = false
238
+ automatically_recover
215
239
  end
216
240
 
217
241
  # @return [Boolean] true if connection is open, false otherwise
@@ -239,19 +263,45 @@ module MarchHare
239
263
 
240
264
  # Defines a connection.blocked handler
241
265
  def on_blocked(&block)
242
- self.add_blocked_listener(BlockBlockedUnblockedListener.for_blocked(block))
266
+ listener = BlockBlockedUnblockedListener.for_blocked(block)
267
+ @blocked_connection_hooks << listener
268
+
269
+ self.add_blocked_listener(listener)
243
270
  end
244
271
 
245
272
  # Defines a connection.unblocked handler
246
273
  def on_unblocked(&block)
247
- self.add_blocked_listener(BlockBlockedUnblockedListener.for_unblocked(block))
274
+ listener = BlockBlockedUnblockedListener.for_unblocked(block)
275
+ @blocked_connection_hooks << listener
276
+
277
+ self.add_blocked_listener(listener)
278
+ end
279
+
280
+ def add_blocked_listener(listener)
281
+ @connection.add_blocked_listener(listener)
248
282
  end
249
283
 
250
284
  # Clears all callbacks defined with #on_blocked and #on_unblocked.
251
285
  def clear_blocked_connection_callbacks
286
+ @blocked_connection_hooks.clear
287
+
252
288
  @connection.clear_blocked_listeners
253
289
  end
254
290
 
291
+ def on_recovery_start(&block)
292
+ listener = RecoveryListener.for_start(block)
293
+ @connection_recovery_hooks << listener
294
+ end
295
+
296
+ def on_recovery(&block)
297
+ listener = RecoveryListener.for_finish(block)
298
+ @connection_recovery_hooks << listener
299
+ end
300
+
301
+ # Clears all callbacks defined with #on_recovery_started and #on_recovery
302
+ def clear_connection_recovery_callbacks
303
+ @connection_recovery_hooks.clear
304
+ end
255
305
 
256
306
  # @private
257
307
  def add_automatic_recovery_hook
@@ -277,6 +327,11 @@ module MarchHare
277
327
  # Begins automatic connection recovery (typically only used internally
278
328
  # to recover from network failures)
279
329
  def automatically_recover
330
+ raise ConnectionClosedException if @was_explicitly_closed
331
+ @logger.debug("session: begin automatic connection recovery #{Thread.current.inspect}")
332
+
333
+ fire_recovery_start_hooks
334
+
280
335
  ms = @network_recovery_interval * 1000
281
336
  # recovering immediately makes little sense. Wait a bit first. MK.
282
337
  java.lang.Thread.sleep(ms)
@@ -285,6 +340,7 @@ module MarchHare
285
340
  reconnecting_on_network_failures(ms) { build_new_connection }
286
341
  end
287
342
  self.recover_shutdown_hooks(new_connection)
343
+ self.recover_connection_block_hooks(new_connection)
288
344
 
289
345
  # sorting channels by id means that the cases like the following:
290
346
  #
@@ -302,21 +358,33 @@ module MarchHare
302
358
  begin
303
359
  ch.automatically_recover(self, new_connection)
304
360
  rescue Exception, java.io.IOException => e
305
- # TODO: logging
306
- $stderr.puts e
361
+ @logger.error(e)
307
362
  end
308
363
  end
309
364
 
310
365
  @connection = new_connection
366
+
367
+ fire_recovery_hooks
368
+
369
+ @connection
311
370
  end
312
371
 
313
372
  # @private
314
373
  def recover_shutdown_hooks(connection)
374
+ @logger.debug("session: recover_shutdown_hooks")
315
375
  @shutdown_hooks.each do |sh|
316
376
  connection.add_shutdown_listener(sh)
317
377
  end
318
378
  end
319
379
 
380
+ # @private
381
+ def recover_connection_block_hooks(connection)
382
+ @logger.debug("session: recover_connection_block_hooks")
383
+ @blocked_connection_hooks.each do |listener|
384
+ connection.add_blocked_listener(listener)
385
+ end
386
+ end
387
+
320
388
  # Flushes the socket used by this connection.
321
389
  def flush
322
390
  @connection.flush
@@ -401,7 +469,7 @@ module MarchHare
401
469
  end
402
470
 
403
471
  # @private
404
- def self.adresses_from(options)
472
+ def self.addresses_from(options)
405
473
  options[:addresses] || options[:hosts] || [address_with_port_from(options)]
406
474
  end
407
475
 
@@ -485,13 +553,16 @@ module MarchHare
485
553
  end
486
554
 
487
555
  # @private
488
- def self.exception_handler_from(opts)
489
- opts[:exception_handler]
490
- end
491
-
492
- # @private
493
- def self.include_exception_handler?(opts)
494
- !!opts[:exception_handler]
556
+ def endpoint_info_from(cf)
557
+ if @uses_uri
558
+ uri_without_credentials = URI.parse(@uri).tap do |u|
559
+ u.password = "REDACTED"
560
+ u.to_s
561
+ end
562
+ "Target URI: #{uri_without_credentials}"
563
+ else
564
+ "Target host list: #{@addresses.join(', ')}, target virtual host: #{cf.virtual_host}, username: #{cf.username}"
565
+ end
495
566
  end
496
567
 
497
568
  # Executes a block, catching Java exceptions RabbitMQ Java client throws and
@@ -501,28 +572,30 @@ module MarchHare
501
572
  def converting_rjc_exceptions_to_ruby(&block)
502
573
  begin
503
574
  block.call
504
- rescue java.net.ConnectException => e
505
- raise ConnectionRefused.new("Connection to #{@cf.host}:#{@cf.port} refused")
506
- rescue java.net.NoRouteToHostException => e
507
- raise ConnectionRefused.new("Connection to #{@cf.host}:#{@cf.port} failed: no route to host")
508
- rescue java.net.UnknownHostException => e
509
- raise ConnectionRefused.new("Connection to #{@cf.host}:#{@cf.port} refused: host unknown")
510
- rescue java.net.SocketException => e
511
- raise ConnectionRefused.new("Connection to #{@cf.host}:#{@cf.port} failed")
512
- rescue java.util.concurrent.TimeoutException => e
513
- raise ConnectionRefused.new("Connection to #{@cf.host}:#{@cf.port} failed: timeout")
514
- rescue com.rabbitmq.client.AuthenticationFailureException => e
575
+ rescue java.net.ConnectException
576
+ raise ConnectionRefused.new("Connection was refused. #{endpoint_info_from(@cf)}")
577
+ rescue java.net.NoRouteToHostException
578
+ raise ConnectionRefused.new("Connection failed: no route to target host. #{endpoint_info_from(@cf)}")
579
+ rescue java.net.UnknownHostException
580
+ raise ConnectionRefused.new("Connection refused: target host unknown (cannot be resolved). #{endpoint_info_from(@cf)}")
581
+ rescue java.net.SocketException
582
+ raise ConnectionRefused.new("Connection failed due to a socket exception. #{endpoint_info_from(@cf)}")
583
+ rescue java.util.concurrent.TimeoutException
584
+ raise ConnectionRefused.new("Connection timed out. #{endpoint_info_from(@cf)}")
585
+ rescue com.rabbitmq.client.AuthenticationFailureException
515
586
  raise AuthenticationFailureError.new(@cf.username, @cf.virtual_host, @cf.password.bytesize)
516
- rescue com.rabbitmq.client.PossibleAuthenticationFailureException => e
587
+ rescue com.rabbitmq.client.PossibleAuthenticationFailureException
517
588
  raise PossibleAuthenticationFailureError.new(@cf.username, @cf.virtual_host, @cf.password.bytesize)
518
589
  end
519
590
  end
520
591
 
521
592
  # @private
522
593
  def reconnecting_on_network_failures(interval_in_ms, &fn)
594
+ @logger.debug("session: reconnecting_on_network_failures")
523
595
  begin
596
+ return if @was_explicitly_closed
524
597
  fn.call
525
- rescue IOError, MarchHare::ConnectionRefused, java.io.IOException, java.util.concurrent.TimeoutException => e
598
+ rescue IOError, MarchHare::ConnectionRefused, java.io.IOException, java.util.concurrent.TimeoutException
526
599
  java.lang.Thread.sleep(interval_in_ms)
527
600
 
528
601
  retry
@@ -531,7 +604,13 @@ module MarchHare
531
604
 
532
605
  # @private
533
606
  def build_new_connection
534
- @uses_uri ? new_uri_connection_impl(@uri) : new_connection_impl(@addresses)
607
+ if @uses_uri
608
+ @logger.debug("session: instantiating a new connection using a URI")
609
+ new_uri_connection_impl(@uri)
610
+ else
611
+ @logger.debug("session: instantiating a new connection using a set of addresses: #{@addresses.join(',')}")
612
+ new_connection_impl(@addresses)
613
+ end
535
614
  end
536
615
 
537
616
  # @private
@@ -608,6 +687,48 @@ module MarchHare
608
687
  self.class.tls_certificate_password_from(opts)
609
688
  end
610
689
 
690
+ # @private
691
+ def init_default_exception_handler(logger)
692
+ ExceptionHandler.new(logger)
693
+ end
694
+
695
+ # @private
696
+ def init_default_logger(logfile, level)
697
+ lgr = ::Logger.new(logfile)
698
+ lgr.level = normalize_log_level(level)
699
+ lgr.progname = self.to_s
700
+ lgr
701
+ end
702
+
703
+ # @private
704
+ def normalize_log_level(level)
705
+ case level
706
+ when :debug, Logger::DEBUG, "debug" then Logger::DEBUG
707
+ when :info, Logger::INFO, "info" then Logger::INFO
708
+ when :warn, Logger::WARN, "warn" then Logger::WARN
709
+ when :error, Logger::ERROR, "error" then Logger::ERROR
710
+ when :fatal, Logger::FATAL, "fatal" then Logger::FATAL
711
+ else
712
+ Logger::WARN
713
+ end
714
+ end
715
+
716
+ # @private
717
+ def fire_recovery_start_hooks
718
+ @logger.debug "Have #{@connection_recovery_hooks.size} recovery start hooks to run"
719
+ @connection_recovery_hooks.each do |recovery_listener|
720
+ recovery_listener.handle_recovery_started(self)
721
+ end
722
+ end
723
+
724
+ # @private
725
+ def fire_recovery_hooks
726
+ @logger.debug "Have #{@connection_recovery_hooks.size} recovery completion hooks to run"
727
+ @connection_recovery_hooks.each do |recovery_listener|
728
+ recovery_listener.handle_recovery(self)
729
+ end
730
+ end
731
+
611
732
  # Ruby blocks-based BlockedListener that handles
612
733
  # connection.blocked and connection.unblocked.
613
734
  # @private
@@ -646,5 +767,32 @@ module MarchHare
646
767
  end
647
768
  end
648
769
 
770
+ # Ruby blocks-based RecoveryListener that handles
771
+ # connection recovery_started and recovery
772
+ class RecoveryListener
773
+ NOOP_FN1 = Proc.new { |_| }
774
+ private_constant :NOOP_FN1
775
+
776
+ def self.for_start(block)
777
+ new(block, NOOP_FN1)
778
+ end
779
+
780
+ def self.for_finish(block)
781
+ new(NOOP_FN1, block)
782
+ end
783
+
784
+ def initialize(before_recovery, after_recovery)
785
+ @recovery_start_hook = before_recovery
786
+ @recovery_hook = after_recovery
787
+ end
788
+
789
+ def handle_recovery_started(recoverable)
790
+ @recovery_start_hook.call(recoverable)
791
+ end
792
+
793
+ def handle_recovery(recoverable)
794
+ @recovery_hook.call(recoverable)
795
+ end
796
+ end
649
797
  end
650
798
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module MarchHare
4
- VERSION = "3.1.1"
4
+ VERSION = "4.3.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: march_hare
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 4.3.0
5
5
  platform: java
6
6
  authors:
7
7
  - Theo Hultberg
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-03-01 00:00:00.000000000 Z
12
+ date: 2020-09-30 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: RabbitMQ client for JRuby built around the official RabbitMQ Java client
15
15
  email:
@@ -27,6 +27,7 @@ files:
27
27
  - lib/march_hare/consumers.rb
28
28
  - lib/march_hare/consumers/base.rb
29
29
  - lib/march_hare/consumers/blocking.rb
30
+ - lib/march_hare/exception_handler.rb
30
31
  - lib/march_hare/exceptions.rb
31
32
  - lib/march_hare/exchange.rb
32
33
  - lib/march_hare/juc.rb
@@ -55,8 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
56
  - !ruby/object:Gem::Version
56
57
  version: '0'
57
58
  requirements: []
58
- rubyforge_project: march_hare
59
- rubygems_version: 2.6.13
59
+ rubygems_version: 3.0.6
60
60
  signing_key:
61
61
  specification_version: 4
62
62
  summary: RabbitMQ client for JRuby built around the official RabbitMQ Java client