bunny 2.21.0 → 2.23.0

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: a51dd17b606b2363463849ba249e8bdff82f263237304def85c72d804a72cf9f
4
- data.tar.gz: fc7754eb6f23de9759b515f9c98800ff24ecc0b1dea4d07a6a04f028362a91f2
3
+ metadata.gz: b33407ce8bf5340f646d7f35f884b991da2c54b1e46e7c8bd31f65e75822cc22
4
+ data.tar.gz: 8b4242b14294c62a4310f6f4921eabb54414d930756495ab1c9130559475593f
5
5
  SHA512:
6
- metadata.gz: 522d80a40d4189fe483ad77f213f676afabbf6d27d834ebb84c6cf2c79f11060f11015e0b2fe92cf08e0fa5144244b94f7f36c785db43577722660e216b7039c
7
- data.tar.gz: 7d2e4905752d86fadd6ac8d780970c4e8abd622cdb3b93aa94503bc4f03b3c658bbc6901c110bcf1dc16e18610aa2f7e57bae061525eb879b1d2e43ba4a3fcb2
6
+ metadata.gz: 7ecfba958caee454e1105cd500a1d2f632340b8358469420802b8fbf029abdedc742bdae39ff9d2ad1b04cc4a7d7fd6bc26b1ff11fc282118c6c05fb688ff661
7
+ data.tar.gz: 7b101718ac037ad85702432cdf865310e94c5a269348ceee714bc6e5630312415f87283360dbbe88577fa1b661ecc5e5f8086d59bbdd50098cfe5e528c757ea1
data/lib/bunny/channel.rb CHANGED
@@ -378,7 +378,7 @@ module Bunny
378
378
  # @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
379
379
  # @api public
380
380
  def default_exchange
381
- Exchange.default(self)
381
+ @default_exchange ||= Exchange.default(self)
382
382
  end
383
383
 
384
384
  # Declares a headers exchange or looks it up in the cache of previously
@@ -396,7 +396,7 @@ module Bunny
396
396
  # @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
397
397
  # @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
398
398
  def exchange(name, opts = {})
399
- Exchange.new(self, opts.fetch(:type, :direct), name, opts)
399
+ find_exchange(name) || Exchange.new(self, opts.fetch(:type, :direct), name, opts)
400
400
  end
401
401
 
402
402
  # @endgroup
@@ -1536,7 +1536,8 @@ module Bunny
1536
1536
  # @return [String] Unique string.
1537
1537
  # @api plugin
1538
1538
  def generate_consumer_tag(name = "bunny")
1539
- "#{name}-#{Time.now.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
1539
+ t = Bunny::Timestamp.now
1540
+ "#{name}-#{t.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
1540
1541
  end
1541
1542
 
1542
1543
  # @endgroup
@@ -1819,7 +1820,7 @@ module Bunny
1819
1820
 
1820
1821
  # @private
1821
1822
  def channel_level_exception_after_operation_that_has_no_response?(method)
1822
- method.reply_code == 406 && method.reply_text =~ /unknown delivery tag/
1823
+ method.reply_code == 406 && (method.reply_text =~ /unknown delivery tag/ || method.reply_text =~ /delivery acknowledgement on channel \d+ timed out/)
1823
1824
  end
1824
1825
 
1825
1826
  # @private
@@ -25,18 +25,19 @@ module Bunny
25
25
  end
26
26
 
27
27
  def poll(timeout_in_ms = nil)
28
- timeout = timeout_in_ms ? timeout_in_ms / 1000.0 : nil
28
+ timeout_in_sec = timeout_in_ms ? timeout_in_ms / 1000.0 : nil
29
29
 
30
30
  @lock.synchronize do
31
- timeout_strikes_at = Time.now.utc + (timeout || 0)
31
+ started_at = Bunny::Timestamp.monotonic
32
32
  while @q.empty?
33
- wait = if timeout
34
- timeout_strikes_at - Time.now.utc
35
- else
36
- nil
37
- end
38
- @cond.wait(@lock, wait)
39
- raise ::Timeout::Error if wait && Time.now.utc >= timeout_strikes_at
33
+ wait = !(timeout_in_sec.nil?)
34
+ @cond.wait(@lock, timeout_in_sec)
35
+
36
+ if wait
37
+ ended_at = Bunny::Timestamp.monotonic
38
+ elapsed = ended_at - started_at
39
+ raise ::Timeout::Error if (elapsed > timeout_in_sec)
40
+ end
40
41
  end
41
42
  item = @q.shift
42
43
  item
@@ -8,7 +8,8 @@ module Bunny
8
8
 
9
9
  # @return [String] Generated consumer tag
10
10
  def generate
11
- "#{Kernel.rand}-#{Time.now.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
11
+ t = Bunny::Timestamp.now
12
+ "#{Kernel.rand}-#{t.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
12
13
  end # generate
13
14
 
14
15
 
@@ -17,7 +18,8 @@ module Bunny
17
18
  # @return [String] Unique string.
18
19
  # @api public
19
20
  def generate_prefixed(name = "bunny")
20
- "#{name}-#{Time.now.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
21
+ t = Bunny::Timestamp.now
22
+ "#{name}-#{t.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
21
23
  end
22
24
  end
23
25
  end
@@ -17,7 +17,7 @@ module Bunny
17
17
  @logger = logger
18
18
  @mutex = Monitor.new
19
19
 
20
- @last_activity_time = Time.now
20
+ @last_activity_time = Bunny::Timestamp.monotonic
21
21
  end
22
22
 
23
23
  def start(period = 30)
@@ -38,7 +38,7 @@ module Bunny
38
38
  end
39
39
 
40
40
  def signal_activity!
41
- @last_activity_time = Time.now
41
+ @last_activity_time = Bunny::Timestamp.monotonic
42
42
  end
43
43
 
44
44
  protected
@@ -53,14 +53,14 @@ module Bunny
53
53
  rescue IOError => ioe
54
54
  @logger.error "I/O error in the hearbeat sender: #{ioe.message}"
55
55
  stop
56
- rescue Exception => e
56
+ rescue ::Exception => e
57
57
  @logger.error "Error in the hearbeat sender: #{e.message}"
58
58
  stop
59
59
  end
60
60
  end
61
61
 
62
62
  def beat
63
- now = Time.now
63
+ now = Bunny::Timestamp.monotonic
64
64
 
65
65
  if now > (@last_activity_time + @interval)
66
66
  @logger.debug { "Sending a heartbeat, last activity time: #{@last_activity_time}, interval (s): #{@interval}" }
data/lib/bunny/session.rb CHANGED
@@ -128,6 +128,7 @@ module Bunny
128
128
  # @option connection_string_or_opts [Integer] :reset_recovery_attempts_after_reconnection (true) Should recovery attempt counter be reset after successful reconnection? When set to false, the attempt counter will last through the entire lifetime of the connection object.
129
129
  # @option connection_string_or_opts [Proc] :recovery_attempt_started (nil) Will be called before every connection recovery attempt
130
130
  # @option connection_string_or_opts [Proc] :recovery_completed (nil) Will be called after successful connection recovery
131
+ # @option connection_string_or_opts [Proc] :recovery_attempts_exhausted (nil) Will be called when the connection recovery failed after the specified amount of recovery attempts
131
132
  # @option connection_string_or_opts [Boolean] :recover_from_connection_close (true) Should this connection recover after receiving a server-sent connection.close (e.g. connection was force closed)?
132
133
  # @option connection_string_or_opts [Object] :session_error_handler (Thread.current) Object which responds to #raise that will act as a session error handler. Defaults to Thread.current, which will raise asynchronous exceptions in the thread that created the session.
133
134
  #
@@ -225,6 +226,7 @@ module Bunny
225
226
 
226
227
  @recovery_attempt_started = opts[:recovery_attempt_started]
227
228
  @recovery_completed = opts[:recovery_completed]
229
+ @recovery_attempts_exhausted = opts[:recovery_attempts_exhausted]
228
230
 
229
231
  @session_error_handler = opts.fetch(:session_error_handler, Thread.current)
230
232
 
@@ -553,6 +555,12 @@ module Bunny
553
555
  @recovery_completed = block
554
556
  end
555
557
 
558
+ # Defines a callable (e.g. a block) that will be called
559
+ # when the connection recovery failed after the specified
560
+ # numbers of recovery attempts.
561
+ def after_recovery_attempts_exhausted(&block)
562
+ @recovery_attempts_exhausted = block
563
+ end
556
564
 
557
565
  #
558
566
  # Implementation
@@ -809,6 +817,7 @@ module Bunny
809
817
  @transport.close
810
818
  self.close(false)
811
819
  @manually_closed = false
820
+ notify_of_recovery_attempts_exhausted
812
821
  end
813
822
  else
814
823
  raise e
@@ -859,6 +868,11 @@ module Bunny
859
868
  @recovery_completed.call if @recovery_completed
860
869
  end
861
870
 
871
+ # @private
872
+ def notify_of_recovery_attempts_exhausted
873
+ @recovery_attempts_exhausted.call if @recovery_attempts_exhausted
874
+ end
875
+
862
876
  # @private
863
877
  def instantiate_connection_level_exception(frame)
864
878
  case frame
@@ -0,0 +1,22 @@
1
+ module Bunny
2
+ # Abstracts away the Ruby (OS) method of retriving timestamps.
3
+ #
4
+ # @private
5
+ class Timestamp
6
+ def self.now
7
+ ::Time.now
8
+ end
9
+
10
+ def self.monotonic
11
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
12
+ end
13
+
14
+ def self.non_monotonic
15
+ ::Time.now
16
+ end
17
+
18
+ def self.non_monotonic_utc
19
+ self.non_monotonic.utc
20
+ end
21
+ end
22
+ end
data/lib/bunny/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Bunny
4
4
  # @return [String] Version of the library
5
- VERSION = "2.21.0"
5
+ VERSION = "2.23.0"
6
6
  end
data/lib/bunny.rb CHANGED
@@ -10,7 +10,7 @@ require "bunny/framing"
10
10
  require "bunny/exceptions"
11
11
 
12
12
  require "bunny/socket"
13
-
13
+ require "bunny/timestamp"
14
14
  require "bunny/timeout"
15
15
 
16
16
  begin
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.21.0
4
+ version: 2.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Duncan
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2023-06-08 00:00:00.000000000 Z
15
+ date: 2024-07-01 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: amq-protocol
@@ -98,13 +98,15 @@ files:
98
98
  - lib/bunny/ssl_socket.rb
99
99
  - lib/bunny/test_kit.rb
100
100
  - lib/bunny/timeout.rb
101
+ - lib/bunny/timestamp.rb
101
102
  - lib/bunny/transport.rb
102
103
  - lib/bunny/version.rb
103
104
  - lib/bunny/versioned_delivery_tag.rb
104
105
  homepage: http://rubybunny.info
105
106
  licenses:
106
107
  - MIT
107
- metadata: {}
108
+ metadata:
109
+ changelog_uri: https://github.com/ruby-amqp/bunny/blob/main/ChangeLog.md
108
110
  post_install_message:
109
111
  rdoc_options: []
110
112
  require_paths:
@@ -120,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
122
  - !ruby/object:Gem::Version
121
123
  version: '0'
122
124
  requirements: []
123
- rubygems_version: 3.4.6
125
+ rubygems_version: 3.5.9
124
126
  signing_key:
125
127
  specification_version: 4
126
128
  summary: Popular easy to use Ruby client for RabbitMQ