march_hare 3.1.1-java → 4.0.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: 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