bunny 2.21.0 → 2.23.0

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: 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