amq-protocol 2.6.0 → 2.8.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: 0b58eb9e3a561cb4902e3a1b2526a47b68d4f0b5431f459fd87cce35cd6936bc
4
- data.tar.gz: 21257ef030688922961fdeaf4a83d64b8ab3c21688e53c5fc41bf083b2277f1f
3
+ metadata.gz: 7cd695fb0f7f7cc8c9d80109f349fdba92c500b5b8eea4ff6ea2c5e6dfdddd8d
4
+ data.tar.gz: 929be34e6f1bd9c2f84fded2933e9f3775286e19babbabac45ce0ccab1b3c38d
5
5
  SHA512:
6
- metadata.gz: 6e80602244a9d0768c9fbe24d16c0acc884205d9ebf41142bf69963dad829c60170b299b7b8ee43734299f7eb45be2d54b36ca58ef4de0196fc142bd68f70d3c
7
- data.tar.gz: ea1f03bf20b010e0fbc23b1c8441ee6de0b71202b8f3b0a3a7b7574510b8a682eddcc7982caee8fbcb24c0b566bc6d9e67b485990ad40b67f291d8fbccadd0f9
6
+ metadata.gz: 990e85acbfc80b8dbfa1be036705afdef1f96fdae2b1c8270ff00c972483925361d9dbb7807309fca6a0db55c3d795f8da34d3255f153ff463cda2d12ceed918
7
+ data.tar.gz: 62f8b49269c978f162a21aced9eb22702ae676e28589da94f66b1560083c66878584a1999fa0611f4be1f205a402539b228f0d165107dc930d7a7112801cb8aa
data/ChangeLog.md CHANGED
@@ -1,7 +1,29 @@
1
- ## Changes between 2.6.0 and 2.7.0 (unreleased)
1
+ ## Changes between 2.8.0 and 2.9.0 (unreleased)
2
2
 
3
3
  No changes yet.
4
4
 
5
+ ## Changes between 2.7.0 and 2.8.0 (Apr 25, 2026)
6
+
7
+ ### Performance Improvements in Frame Decoding and Encoding
8
+
9
+ Replacing `x == nil` with `x.nil?` in the frame layer hot path yields a
10
+ consistent **+15–18% throughput improvement** in `Frame.decode_header`
11
+ (called on every received frame) and **+12–14%** in `HeartbeatFrame.encode`,
12
+ across Ruby 3.3, 3.4, and 4.0.
13
+
14
+ See benchmarks/BENCHMARKS.md for instructions on how to reproduce these numbers on your machine.
15
+
16
+ Contributed by @eglitobias.
17
+
18
+ GitHub issue: [#86](https://github.com/ruby-amqp/amq-protocol/pull/86)
19
+
20
+
21
+ ## Changes between 2.6.0 and 2.7.0 (Mar 31, 2026)
22
+
23
+ ### Channel.Close Predicates Now Return True Boolean
24
+
25
+ And not just truthy values (values that are not `nil` or `false`).
26
+
5
27
 
6
28
  ## Changes between 2.5.1 and 2.6.0 (Mar 30, 2026)
7
29
 
@@ -40,7 +62,7 @@ Optimized encoding and decoding hot paths:
40
62
  * Switched to `unpack1` instead of `unpack().first` throughout
41
63
  * Use `byteslice` instead of `slice` for binary string operations
42
64
  * Use `getbyte` for single byte access (4x faster than alternatives)
43
- * Adopted `frozen_string_literal` pragma
65
+ * Adopted the `frozen_string_literal` pragma
44
66
 
45
67
  The improvements on Ruby 3.4 are very meaningful:
46
68
 
data/lib/amq/bit_set.rb CHANGED
@@ -113,7 +113,7 @@ module AMQ
113
113
 
114
114
  def check_range(i)
115
115
  if i < 0 || i >= @nbits
116
- raise IndexError.new("Cannot access bit #{i} from a BitSet with #{@nbits} bits")
116
+ raise IndexError, "Cannot access bit #{i} from a BitSet with #{@nbits} bits"
117
117
  end
118
118
  end # check_range
119
119
  end # BitSet
@@ -26,13 +26,12 @@ module AMQ
26
26
  # @param [Integer] hi Upper boundary of the integer range available for allocation
27
27
  # @raise [ArgumentError] if upper boundary is not greater than the lower one
28
28
  def initialize(lo, hi)
29
- raise ArgumentError.new "upper boundary must be greater than the lower one (given: hi = #{hi}, lo = #{lo})" unless hi > lo
29
+ raise ArgumentError, "upper boundary must be greater than the lower one (given: hi = #{hi}, lo = #{lo})" unless hi > lo
30
30
 
31
31
  @hi = hi
32
32
  @lo = lo
33
33
 
34
34
  @number_of_bits = hi - lo
35
- @range = Range.new(1, @number_of_bits)
36
35
  @free_set = BitSet.new(@number_of_bits)
37
36
  end # initialize(hi, lo)
38
37
 
@@ -47,7 +46,7 @@ module AMQ
47
46
 
48
47
  if n = @free_set.next_clear_bit
49
48
 
50
- if n < @hi - 1 then
49
+ if n < @hi - 1
51
50
  @free_set.set(n)
52
51
  n + 1
53
52
  else
@@ -6,17 +6,17 @@ module AMQ
6
6
  class Close
7
7
  # @return [Boolean] true if the channel was closed due to a consumer delivery acknowledgement timeout
8
8
  def delivery_ack_timeout?
9
- reply_code == 406 && reply_text =~ /delivery acknowledgement on channel \d+ timed out/
9
+ reply_code == 406 && reply_text.match?(/delivery acknowledgement on channel \d+ timed out/)
10
10
  end
11
11
 
12
12
  # @return [Boolean] true if the channel was closed due to an unknown delivery tag (e.g. double ack)
13
13
  def unknown_delivery_tag?
14
- reply_code == 406 && reply_text =~ /unknown delivery tag/
14
+ reply_code == 406 && reply_text.match?(/unknown delivery tag/)
15
15
  end
16
16
 
17
17
  # @return [Boolean] true if the channel was closed because a message exceeded the configured max size
18
18
  def message_too_large?
19
- reply_code == 406 && reply_text =~ /larger than configured max size/
19
+ reply_code == 406 && reply_text.match?(/larger than configured max size/)
20
20
  end
21
21
  end
22
22
  end
@@ -173,9 +173,7 @@ module AMQ
173
173
  limit = frame_size - 8
174
174
  return [BodyFrame.new(body, channel)] if body.bytesize < limit
175
175
 
176
- # Otherwise String#slice on 1.9 will operate with code points,
177
- # and we need bytes. MK.
178
- body.force_encoding("ASCII-8BIT") if RUBY_VERSION.to_f >= 1.9 && body.encoding != Encoding::BINARY
176
+ body.force_encoding("ASCII-8BIT") if body.encoding != Encoding::BINARY
179
177
 
180
178
  array = Array.new
181
179
  while body && !body.empty?
@@ -23,8 +23,8 @@ module AMQ
23
23
 
24
24
  # The channel number is 0 for all frames which are global to the connection and 1-65535 for frames that refer to specific channels.
25
25
  def self.encode_to_array(type, payload, channel)
26
- raise RuntimeError.new("Channel has to be 0 or an integer in range 1..65535 but was #{channel.inspect}") unless CHANNEL_RANGE.include?(channel)
27
- raise RuntimeError.new("Payload can't be nil") if payload.nil?
26
+ raise RuntimeError, "Channel has to be 0 or an integer in range 1..65535 but was #{channel.inspect}" unless CHANNEL_RANGE.include?(channel)
27
+ raise RuntimeError, "Payload can't be nil" if payload.nil?
28
28
  components = []
29
29
  components << [find_type(type), channel, payload.bytesize].pack(PACK_CHAR_UINT16_UINT32)
30
30
  components << encoded_payload(payload)
@@ -47,13 +47,13 @@ module AMQ
47
47
  end
48
48
 
49
49
  def self.find_type(type)
50
- type_id = if Symbol === type then TYPES[type] else type end
51
- raise FrameTypeError.new(TYPES_OPTIONS) if type == nil || !TYPES_REVERSE.has_key?(type_id)
50
+ type_id = type.is_a?(Symbol) ? TYPES[type] : type
51
+ raise FrameTypeError, TYPES_OPTIONS if type.nil? || !TYPES_REVERSE.key?(type_id)
52
52
  type_id
53
53
  end
54
54
 
55
55
  def self.decode(*)
56
- raise NotImplementedError.new <<-EOF
56
+ raise NotImplementedError, <<-EOF
57
57
  You are supposed to redefine this method, because it's dependent on used IO adapter.
58
58
 
59
59
  This functionality is part of the https://github.com/ruby-amqp/amq-client library.
@@ -62,12 +62,12 @@ This functionality is part of the https://github.com/ruby-amqp/amq-client librar
62
62
 
63
63
  # Optimized header decode using unpack1 for single values where appropriate
64
64
  def self.decode_header(header)
65
- raise EmptyResponseError if header == nil || header.empty?
65
+ raise EmptyResponseError if header.nil? || header.empty?
66
66
 
67
67
  # Use unpack for multiple values - this is the optimal approach
68
68
  type_id, channel, size = header.unpack(PACK_CHAR_UINT16_UINT32)
69
69
  type = TYPES_REVERSE[type_id]
70
- raise FrameTypeError.new(TYPES_OPTIONS) unless type
70
+ raise FrameTypeError, TYPES_OPTIONS unless type
71
71
  [type, channel, size]
72
72
  end
73
73
 
@@ -83,7 +83,7 @@ module AMQ
83
83
  v, offset = decode_array(data, offset)
84
84
  v
85
85
  else
86
- raise ArgumentError.new("unsupported type in a table value: #{type.inspect}, do not know how to decode!")
86
+ raise ArgumentError, "unsupported type in a table value: #{type.inspect}, do not know how to decode!"
87
87
  end
88
88
 
89
89
  ary << i
@@ -72,7 +72,7 @@ module AMQ
72
72
  accumulator << [0, value.to_i].pack(PACK_UCHAR_UINT32)
73
73
  end
74
74
  else
75
- raise ArgumentError.new("Unsupported value #{value.inspect} of type #{value.class.name}")
75
+ raise ArgumentError, "Unsupported value #{value.inspect} of type #{value.class.name}"
76
76
  end # if
77
77
  end # case
78
78
 
@@ -1,5 +1,5 @@
1
1
  module AMQ
2
2
  module Protocol
3
- VERSION = "2.6.0"
3
+ VERSION = "2.8.0"
4
4
  end # Protocol
5
5
  end # AMQ
data/lib/amq/uri.rb CHANGED
@@ -31,7 +31,9 @@ module AMQ
31
31
 
32
32
  def self.parse(connection_string)
33
33
  uri = ::URI.parse(connection_string)
34
- raise ArgumentError.new("Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766), learn more at http://bit.ly/ks8MXK") unless %w{amqp amqps}.include?(uri.scheme)
34
+ unless %w{amqp amqps}.include?(uri.scheme)
35
+ raise ArgumentError, "Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766), learn more at http://bit.ly/ks8MXK"
36
+ end
35
37
 
36
38
  opts = DEFAULTS.dup
37
39
 
@@ -42,7 +44,9 @@ module AMQ
42
44
  opts[:port] = uri.port || AMQP_DEFAULT_PORTS[uri.scheme]
43
45
  opts[:ssl] = uri.scheme.to_s.downcase =~ /amqps/i # TODO: rename to tls
44
46
  if uri.path =~ %r{^/(.*)}
45
- raise ArgumentError.new("#{uri} has multiple-segment path; please percent-encode any slashes in the vhost name (e.g. /production => %2Fproduction). Learn more at http://bit.ly/amqp-gem-and-connection-uris") if $1.index('/')
47
+ if $1.index('/')
48
+ raise ArgumentError, "#{uri} has multiple-segment path; please percent-encode any slashes in the vhost name (e.g. /production => %2Fproduction). Learn more at http://bit.ly/amqp-gem-and-connection-uris"
49
+ end
46
50
  opts[:vhost] = ::CGI::unescape($1)
47
51
  end
48
52
 
@@ -63,7 +67,7 @@ module AMQ
63
67
 
64
68
  %w(cacertfile certfile keyfile).each do |tls_option|
65
69
  if query_params[tls_option] && uri.scheme == "amqp"
66
- raise ArgumentError.new("The option '#{tls_option}' can only be used in URIs that use amqps schema")
70
+ raise ArgumentError, "The option '#{tls_option}' can only be used in URIs that use amqps schema"
67
71
  else
68
72
  opts[tls_option.to_sym] = query_params[tls_option]
69
73
  end
@@ -71,7 +75,7 @@ module AMQ
71
75
 
72
76
  %w(verify fail_if_no_peer_cert).each do |tls_option|
73
77
  if query_params[tls_option] && uri.scheme == "amqp"
74
- raise ArgumentError.new("The option '#{tls_option}' can only be used in URIs that use amqps schema")
78
+ raise ArgumentError, "The option '#{tls_option}' can only be used in URIs that use amqps schema"
75
79
  else
76
80
  opts[tls_option.to_sym] = as_boolean(query_params[tls_option])
77
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amq-protocol
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Stastny
@@ -10,7 +10,7 @@ authors:
10
10
  - Mark Abramov
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 1980-01-02 00:00:00.000000000 Z
13
+ date: 2026-04-26 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: |2
16
16
  amq-protocol is an AMQP 0.9.1 serialization library for Ruby. It is not a
@@ -43,7 +43,7 @@ files:
43
43
  - lib/amq/protocol/version.rb
44
44
  - lib/amq/settings.rb
45
45
  - lib/amq/uri.rb
46
- homepage: http://github.com/ruby-amqp/amq-protocol
46
+ homepage: https://github.com/ruby-amqp/amq-protocol
47
47
  licenses:
48
48
  - MIT
49
49
  metadata: {}
@@ -54,14 +54,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
- version: '2.2'
57
+ version: '3.0'
58
58
  required_rubygems_version: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
63
  requirements: []
64
- rubygems_version: 3.6.7
64
+ rubygems_version: 3.6.2
65
65
  specification_version: 4
66
66
  summary: AMQP 0.9.1 encoding & decoding library.
67
67
  test_files: []