march_hare 3.1.1-java → 4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 910cb519cfde61ec8390a0c56db3121eb8e5675a3c5b19d662db8ad9a3f7a8d7
4
- data.tar.gz: 0be92a42c7ea2102c442184d0cc892fb171a83f59a718fc1411514f51b5c4dae
3
+ metadata.gz: e1bc17534b034049e19db4642f26c7062834d26cb31ef1ed191e70e9621a0b3f
4
+ data.tar.gz: 1635809c2a7f65d9d343e57fb34bc46b0df173065db6e64e98579ffcc61fc143
5
5
  SHA512:
6
- metadata.gz: 2224b9d612f2419772a19cee956a433243b9e76a3807c372cca723591ee338ab9a2dfa9353e7bbe25601337189b9ab5468ffde8217e7142442baee97b66f082c
7
- data.tar.gz: f592e103fcb40342e7162cbb9a10808267eeb435b017438ebf9590745684903018ddd1a5aad6d0f80ca4d59b1a85b6b34bfe18c0fe716b2eb0ef2b12843c4d40
6
+ metadata.gz: f292ea76e5912fdef5a1dc5016371632cb1a48679300bf3b603f313b718f424b1b690f92c7bb1285967175f2814a5fcb5a46187bc09467375bb174dbb5220485
7
+ data.tar.gz: 8aff2fb9a7c82779a6ac38a37ba71e09799aee1f1305ac7a2b3948101d48949c6226fedc827bab57f31946d058bc7f1a9866a5c9af86f366f0919321bff89e49
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
@@ -99,14 +99,14 @@ module MarchHare
99
99
  def self.convert(e, unwrap_io_exception = true)
100
100
  case e
101
101
  when java.net.SocketException then
102
- IOError.new
102
+ IOError.new(e.message)
103
103
  when java.io.IOException then
104
104
  c = e.cause
105
105
 
106
106
  if c && unwrap_io_exception
107
107
  convert(c, false)
108
108
  else
109
- IOError.new
109
+ IOError.new(e.message)
110
110
  end
111
111
  when com.rabbitmq.client.AlreadyClosedException then
112
112
  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
+ opts[:logger].info("Using TLS/SSL version #{tls}") if opts[: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
@@ -134,11 +138,19 @@ module MarchHare
134
138
  # @return [Array<MarchHare::Channel>] Channels opened on this connection
135
139
  attr_reader :channels
136
140
 
141
+ # @return [::Logger] Logger instance
142
+ attr_reader :logger
143
+
137
144
 
138
145
  # @private
139
146
  def initialize(connection_factory, opts = {})
140
147
  @cf = connection_factory
141
148
 
149
+ log_file = opts[:log_file] || STDOUT
150
+ log_level = opts[:log_level] || ENV["MARCH_HARE_LOG_LEVEL"] || Logger::WARN
151
+ @logger = opts.fetch(:logger, init_default_logger(log_file, log_level))
152
+ @cf.exception_handler = opts.fetch(:exception_handler, init_default_exception_handler(@logger))
153
+
142
154
  # March Hare uses its own connection recovery implementation and
143
155
  # as of Java client 4.x automatic recovery is enabled by
144
156
  # default. MK.
@@ -165,6 +177,8 @@ module MarchHare
165
177
  end
166
178
  @network_recovery_interval = opts.fetch(:network_recovery_interval, DEFAULT_NETWORK_RECOVERY_INTERVAL)
167
179
  @shutdown_hooks = Array.new
180
+ @blocked_connection_hooks = Array.new
181
+ @connection_recovery_hooks = Array.new
168
182
 
169
183
  if @automatically_recover
170
184
  self.add_automatic_recovery_hook
@@ -239,19 +253,45 @@ module MarchHare
239
253
 
240
254
  # Defines a connection.blocked handler
241
255
  def on_blocked(&block)
242
- self.add_blocked_listener(BlockBlockedUnblockedListener.for_blocked(block))
256
+ listener = BlockBlockedUnblockedListener.for_blocked(block)
257
+ @blocked_connection_hooks << listener
258
+
259
+ self.add_blocked_listener(listener)
243
260
  end
244
261
 
245
262
  # Defines a connection.unblocked handler
246
263
  def on_unblocked(&block)
247
- self.add_blocked_listener(BlockBlockedUnblockedListener.for_unblocked(block))
264
+ listener = BlockBlockedUnblockedListener.for_unblocked(block)
265
+ @blocked_connection_hooks << listener
266
+
267
+ self.add_blocked_listener(listener)
268
+ end
269
+
270
+ def add_blocked_listener(listener)
271
+ @connection.add_blocked_listener(listener)
248
272
  end
249
273
 
250
274
  # Clears all callbacks defined with #on_blocked and #on_unblocked.
251
275
  def clear_blocked_connection_callbacks
276
+ @blocked_connection_hooks.clear
277
+
252
278
  @connection.clear_blocked_listeners
253
279
  end
254
280
 
281
+ def on_recovery_start(&block)
282
+ listener = RecoveryListener.for_start(block)
283
+ @connection_recovery_hooks << listener
284
+ end
285
+
286
+ def on_recovery(&block)
287
+ listener = RecoveryListener.for_finish(block)
288
+ @connection_recovery_hooks << listener
289
+ end
290
+
291
+ # Clears all callbacks defined with #on_recovery_started and #on_recovery
292
+ def clear_connection_recovery_callbacks
293
+ @connection_recovery_hooks.clear
294
+ end
255
295
 
256
296
  # @private
257
297
  def add_automatic_recovery_hook
@@ -277,6 +317,10 @@ module MarchHare
277
317
  # Begins automatic connection recovery (typically only used internally
278
318
  # to recover from network failures)
279
319
  def automatically_recover
320
+ @logger.debug("session: begin automatic connection recovery")
321
+
322
+ fire_recovery_start_hooks
323
+
280
324
  ms = @network_recovery_interval * 1000
281
325
  # recovering immediately makes little sense. Wait a bit first. MK.
282
326
  java.lang.Thread.sleep(ms)
@@ -285,6 +329,7 @@ module MarchHare
285
329
  reconnecting_on_network_failures(ms) { build_new_connection }
286
330
  end
287
331
  self.recover_shutdown_hooks(new_connection)
332
+ self.recover_connection_block_hooks(new_connection)
288
333
 
289
334
  # sorting channels by id means that the cases like the following:
290
335
  #
@@ -302,21 +347,33 @@ module MarchHare
302
347
  begin
303
348
  ch.automatically_recover(self, new_connection)
304
349
  rescue Exception, java.io.IOException => e
305
- # TODO: logging
306
- $stderr.puts e
350
+ @logger.error(e)
307
351
  end
308
352
  end
309
353
 
310
354
  @connection = new_connection
355
+
356
+ fire_recovery_hooks
357
+
358
+ @connection
311
359
  end
312
360
 
313
361
  # @private
314
362
  def recover_shutdown_hooks(connection)
363
+ @logger.debug("session: recover_shutdown_hooks")
315
364
  @shutdown_hooks.each do |sh|
316
365
  connection.add_shutdown_listener(sh)
317
366
  end
318
367
  end
319
368
 
369
+ # @private
370
+ def recover_connection_block_hooks(connection)
371
+ @logger.debug("session: recover_connection_block_hooks")
372
+ @blocked_connection_hooks.each do |listener|
373
+ connection.add_blocked_listener(listener)
374
+ end
375
+ end
376
+
320
377
  # Flushes the socket used by this connection.
321
378
  def flush
322
379
  @connection.flush
@@ -484,16 +541,6 @@ module MarchHare
484
541
  !!opts[:thread_factory]
485
542
  end
486
543
 
487
- # @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]
495
- end
496
-
497
544
  # Executes a block, catching Java exceptions RabbitMQ Java client throws and
498
545
  # transforms them to Ruby exceptions that are then re-raised.
499
546
  #
@@ -520,6 +567,7 @@ module MarchHare
520
567
 
521
568
  # @private
522
569
  def reconnecting_on_network_failures(interval_in_ms, &fn)
570
+ @logger.debug("session: reconnecting_on_network_failures")
523
571
  begin
524
572
  fn.call
525
573
  rescue IOError, MarchHare::ConnectionRefused, java.io.IOException, java.util.concurrent.TimeoutException => e
@@ -531,6 +579,7 @@ module MarchHare
531
579
 
532
580
  # @private
533
581
  def build_new_connection
582
+ @logger.debug("session: instantiating a new connection")
534
583
  @uses_uri ? new_uri_connection_impl(@uri) : new_connection_impl(@addresses)
535
584
  end
536
585
 
@@ -608,6 +657,48 @@ module MarchHare
608
657
  self.class.tls_certificate_password_from(opts)
609
658
  end
610
659
 
660
+ # @private
661
+ def init_default_exception_handler(logger)
662
+ ExceptionHandler.new(logger)
663
+ end
664
+
665
+ # @private
666
+ def init_default_logger(logfile, level)
667
+ lgr = ::Logger.new(logfile)
668
+ lgr.level = normalize_log_level(level)
669
+ lgr.progname = self.to_s
670
+ lgr
671
+ end
672
+
673
+ # @private
674
+ def normalize_log_level(level)
675
+ case level
676
+ when :debug, Logger::DEBUG, "debug" then Logger::DEBUG
677
+ when :info, Logger::INFO, "info" then Logger::INFO
678
+ when :warn, Logger::WARN, "warn" then Logger::WARN
679
+ when :error, Logger::ERROR, "error" then Logger::ERROR
680
+ when :fatal, Logger::FATAL, "fatal" then Logger::FATAL
681
+ else
682
+ Logger::WARN
683
+ end
684
+ end
685
+
686
+ # @private
687
+ def fire_recovery_start_hooks
688
+ @logger.debug "Have #{@connection_recovery_hooks.size} recovery start hooks to run"
689
+ @connection_recovery_hooks.each do |recovery_listener|
690
+ recovery_listener.handle_recovery_started(self)
691
+ end
692
+ end
693
+
694
+ # @private
695
+ def fire_recovery_hooks
696
+ @logger.debug "Have #{@connection_recovery_hooks.size} recovery completion hooks to run"
697
+ @connection_recovery_hooks.each do |recovery_listener|
698
+ recovery_listener.handle_recovery(self)
699
+ end
700
+ end
701
+
611
702
  # Ruby blocks-based BlockedListener that handles
612
703
  # connection.blocked and connection.unblocked.
613
704
  # @private
@@ -646,5 +737,32 @@ module MarchHare
646
737
  end
647
738
  end
648
739
 
740
+ # Ruby blocks-based RecoveryListener that handles
741
+ # connection recovery_started and recovery
742
+ class RecoveryListener
743
+ NOOP_FN1 = Proc.new { |_| }
744
+ private_constant :NOOP_FN1
745
+
746
+ def self.for_start(block)
747
+ new(block, NOOP_FN1)
748
+ end
749
+
750
+ def self.for_finish(block)
751
+ new(NOOP_FN1, block)
752
+ end
753
+
754
+ def initialize(before_recovery, after_recovery)
755
+ @recovery_start_hook = before_recovery
756
+ @recovery_hook = after_recovery
757
+ end
758
+
759
+ def handle_recovery_started(recoverable)
760
+ @recovery_start_hook.call(recoverable)
761
+ end
762
+
763
+ def handle_recovery(recoverable)
764
+ @recovery_hook.call(recoverable)
765
+ end
766
+ end
649
767
  end
650
768
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module MarchHare
4
- VERSION = "3.1.1"
4
+ VERSION = "4.0.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.0.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: 2019-07-05 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.4
60
60
  signing_key:
61
61
  specification_version: 4
62
62
  summary: RabbitMQ client for JRuby built around the official RabbitMQ Java client