bunny 3.1.0 → 3.3.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.
data/lib/bunny/queue.rb CHANGED
@@ -91,8 +91,9 @@ module Bunny
91
91
 
92
92
  # for basic.deliver dispatch and such
93
93
  @channel.register_queue(self)
94
- # for topology recovery
95
- @channel.record_queue(self)
94
+ # for topology recovery. A passive declaration does not own the queue,
95
+ # so it must not overwrite what was recorded for it earlier
96
+ @channel.record_queue(self) unless @options[:passive]
96
97
  end
97
98
 
98
99
  # @return [Boolean] true if this queue was declared as durable (will survive broker restart).
@@ -159,7 +160,7 @@ module Bunny
159
160
  def bind(exchange, opts = {})
160
161
  @channel.queue_bind(@name, exchange, opts)
161
162
 
162
- exchange_name = if exchange.respond_to?(:name)
163
+ exchange_name = if exchange.is_a?(Bunny::Exchange)
163
164
  exchange.name
164
165
  else
165
166
  exchange
@@ -168,7 +169,7 @@ module Bunny
168
169
 
169
170
  # store bindings for automatic recovery. We need to be very careful to
170
171
  # not cause an infinite rebinding loop here when we recover. MK.
171
- binding = { :exchange => exchange_name, :routing_key => (opts[:routing_key] || opts[:key]), :arguments => opts[:arguments] }
172
+ binding = { exchange: exchange_name, routing_key: (opts[:routing_key] || opts[:key]), arguments: opts[:arguments] }
172
173
  @bindings.push(binding) unless @bindings.include?(binding)
173
174
 
174
175
  self
@@ -188,7 +189,7 @@ module Bunny
188
189
  def unbind(exchange, opts = {})
189
190
  @channel.queue_unbind(@name, exchange, opts)
190
191
 
191
- exchange_name = if exchange.respond_to?(:name)
192
+ exchange_name = if exchange.is_a?(Bunny::Exchange)
192
193
  exchange.name
193
194
  else
194
195
  exchange
@@ -214,11 +215,11 @@ module Bunny
214
215
  # @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
215
216
  # @api public
216
217
  def subscribe(opts = {
217
- :consumer_tag => @channel.generate_consumer_tag,
218
- :manual_ack => false,
219
- :exclusive => false,
220
- :block => false,
221
- :on_cancellation => nil
218
+ consumer_tag: @channel.generate_consumer_tag,
219
+ manual_ack: false,
220
+ exclusive: false,
221
+ block: false,
222
+ on_cancellation: nil
222
223
  }, &block)
223
224
 
224
225
  unless opts[:ack].nil?
@@ -256,7 +257,7 @@ module Bunny
256
257
  #
257
258
  # @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
258
259
  # @api public
259
- def subscribe_with(consumer, opts = {:block => false})
260
+ def subscribe_with(consumer, opts = { block: false })
260
261
  @channel.basic_consume_with(consumer)
261
262
 
262
263
  @channel.work_pool.join if opts[:block]
@@ -281,13 +282,13 @@ module Bunny
281
282
  # ch = conn.create_channel
282
283
  # q = ch.queue("test1")
283
284
  # x = ch.default_exchange
284
- # x.publish("Hello, everybody!", :routing_key => 'test1')
285
+ # x.publish("Hello, everybody!", routing_key: 'test1')
285
286
  #
286
287
  # delivery_info, properties, payload = q.pop
287
288
  #
288
289
  # puts "This is the message: " + payload + "\n\n"
289
290
  # conn.close
290
- def pop(opts = {:manual_ack => false}, &block)
291
+ def pop(opts = { manual_ack: false }, &block)
291
292
  unless opts[:ack].nil?
292
293
  warn "[DEPRECATION] `:ack` is deprecated. Please use `:manual_ack` instead."
293
294
  opts[:manual_ack] = opts[:ack]
@@ -323,7 +324,7 @@ module Bunny
323
324
  # @see Bunny::Channel#default_exchange
324
325
  # @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
325
326
  def publish(payload, opts = {})
326
- @channel.default_exchange.publish(payload, opts.merge(:routing_key => @name))
327
+ @channel.default_exchange.publish(payload, opts.merge(routing_key: @name))
327
328
 
328
329
  self
329
330
  end
@@ -357,9 +358,9 @@ module Bunny
357
358
  # @see #message_count
358
359
  # @see #consumer_count
359
360
  def status
360
- queue_declare_ok = @channel.queue_declare(@name, @options.merge(:passive => true))
361
- {:message_count => queue_declare_ok.message_count,
362
- :consumer_count => queue_declare_ok.consumer_count}
361
+ queue_declare_ok = @channel.queue_declare(@name, @options.merge(passive: true))
362
+ { message_count: queue_declare_ok.message_count,
363
+ consumer_count: queue_declare_ok.consumer_count }
363
364
  end
364
365
 
365
366
  # @return [Integer] How many messages the queue has ready (e.g. not delivered but not unacknowledged)
@@ -378,8 +379,8 @@ module Bunny
378
379
  # be extra defensive
379
380
  args = args0 || {}
380
381
  q_type = args["x-queue-type"] || args[:"x-queue-type"]
381
- throw ArgumentError.new(
382
- "unsupported queue type #{q_type.inspect}, supported ones: #{Types::KNOWN.join(', ')}") if (q_type and !Types.known?(q_type))
382
+ raise ArgumentError,
383
+ "unsupported queue type #{q_type.inspect}, supported ones: #{Types::KNOWN.join(', ')}" if (q_type and !Types.known?(q_type))
383
384
  end
384
385
 
385
386
  #
@@ -397,15 +398,15 @@ module Bunny
397
398
  # @private
398
399
  def self.add_default_options(name, opts)
399
400
  # :nowait is always false for Bunny
400
- h = { :queue => name, :nowait => false }.merge(opts)
401
+ h = { queue: name, nowait: false }.merge(opts)
401
402
 
402
403
  if name.empty?
403
404
  {
404
- :passive => false,
405
- :durable => false,
406
- :exclusive => false,
407
- :auto_delete => false,
408
- :arguments => nil
405
+ passive: false,
406
+ durable: false,
407
+ exclusive: false,
408
+ auto_delete: false,
409
+ arguments: nil
409
410
  }.merge(h)
410
411
  else
411
412
  h
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "thread"
4
-
5
3
  module Bunny
6
4
  # Network activity loop that reads and passes incoming AMQP 0.9.1 methods for
7
5
  # processing. They are dispatched further down the line in Bunny::Session and Bunny::Channel.
@@ -41,10 +41,10 @@ module Bunny
41
41
  # @return [Hash] Hash representation of this returned delivery info
42
42
  def to_hash
43
43
  @hash ||= {
44
- :reply_code => @basic_return.reply_code,
45
- :reply_text => @basic_return.reply_text,
46
- :exchange => @basic_return.exchange,
47
- :routing_key => @basic_return.routing_key
44
+ reply_code: @basic_return.reply_code,
45
+ reply_text: @basic_return.reply_text,
46
+ exchange: @basic_return.exchange,
47
+ routing_key: @basic_return.routing_key
48
48
  }
49
49
  end
50
50
 
data/lib/bunny/session.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "socket"
4
- require "thread"
5
- require "monitor"
6
4
 
7
5
  require "bunny/transport"
8
6
  require "bunny/channel_id_allocator"
@@ -51,19 +49,19 @@ module Bunny
51
49
 
52
50
  # RabbitMQ client metadata
53
51
  DEFAULT_CLIENT_PROPERTIES = {
54
- :capabilities => {
55
- :publisher_confirms => true,
56
- :consumer_cancel_notify => true,
57
- :exchange_exchange_bindings => true,
52
+ capabilities: {
53
+ publisher_confirms: true,
54
+ consumer_cancel_notify: true,
55
+ exchange_exchange_bindings: true,
58
56
  :"basic.nack" => true,
59
57
  :"connection.blocked" => true,
60
58
  # See http://www.rabbitmq.com/auth-notification.html
61
- :authentication_failure_close => true
59
+ authentication_failure_close: true
62
60
  },
63
- :product => "Bunny",
64
- :platform => ::RUBY_DESCRIPTION,
65
- :version => Bunny::VERSION,
66
- :information => "https://github.com/ruby-amqp/bunny",
61
+ product: "Bunny",
62
+ platform: ::RUBY_DESCRIPTION,
63
+ version: Bunny::VERSION,
64
+ information: "https://github.com/ruby-amqp/bunny",
67
65
  }
68
66
 
69
67
  # @private
@@ -225,6 +223,7 @@ module Bunny
225
223
  @transport_mutex = @mutex_impl.new
226
224
  @status_mutex = @mutex_impl.new
227
225
  @address_index_mutex = @mutex_impl.new
226
+ @recovery_mutex = @mutex_impl.new
228
227
 
229
228
  @channels = Hash.new
230
229
 
@@ -341,6 +340,10 @@ module Bunny
341
340
  @transport.connect
342
341
  end
343
342
 
343
+ if @transport.read_timeout.nil?
344
+ @transport.read_timeout = @transport.connect_timeout || Transport::DEFAULT_READ_TIMEOUT
345
+ end
346
+
344
347
  self.init_connection
345
348
  self.open_connection
346
349
 
@@ -577,7 +580,7 @@ module Bunny
577
580
  def queue_exists?(name)
578
581
  ch = create_channel
579
582
  begin
580
- ch.queue(name, :passive => true)
583
+ ch.queue(name, passive: true)
581
584
  true
582
585
  rescue Bunny::ResourceLocked => _
583
586
  true
@@ -599,7 +602,7 @@ module Bunny
599
602
  def exchange_exists?(name)
600
603
  ch = create_channel
601
604
  begin
602
- ch.exchange(name, :passive => true)
605
+ ch.exchange(name, passive: true)
603
606
  true
604
607
  rescue Bunny::NotFound => _
605
608
  false
@@ -786,16 +789,18 @@ module Bunny
786
789
  # @private
787
790
  def handle_frameset(ch_number, frames)
788
791
  method = frames.first
792
+ ch = find_channel(ch_number)
793
+
794
+ unless ch
795
+ @logger.warn "Channel #{ch_number} is not open on this connection!"
796
+ return
797
+ end
789
798
 
790
799
  case method
791
- when AMQ::Protocol::Basic::GetOk then
792
- @channels[ch_number].handle_basic_get_ok(*frames)
793
- when AMQ::Protocol::Basic::GetEmpty then
794
- @channels[ch_number].handle_basic_get_empty(*frames)
795
- when AMQ::Protocol::Basic::Return then
796
- @channels[ch_number].handle_basic_return(*frames)
797
- else
798
- @channels[ch_number].handle_frameset(*frames)
800
+ when AMQ::Protocol::Basic::GetOk then ch.handle_basic_get_ok(*frames)
801
+ when AMQ::Protocol::Basic::GetEmpty then ch.handle_basic_get_empty(*frames)
802
+ when AMQ::Protocol::Basic::Return then ch.handle_basic_return(*frames)
803
+ else ch.handle_frameset(*frames)
799
804
  end
800
805
  end
801
806
 
@@ -810,30 +815,51 @@ module Bunny
810
815
 
811
816
  @status_mutex.synchronize { @status = :disconnected }
812
817
 
813
- if !recovering_from_network_failure?
814
- begin
818
+ acquired = @recovery_mutex.synchronize do
819
+ if @recovering_from_network_failure
820
+ false
821
+ else
815
822
  @recovering_from_network_failure = true
816
- if recoverable_network_failure?(exception)
817
- announce_network_failure_recovery
818
- @channel_mutex.synchronize do
819
- @channels.each do |n, ch|
820
- ch.connection_closed!
821
- ch.maybe_kill_consumer_work_pool!
822
- end
823
+ end
824
+ end
825
+ return unless acquired
826
+
827
+ begin
828
+ if recoverable_network_failure?(exception)
829
+ announce_network_failure_recovery
830
+ @channel_mutex.synchronize do
831
+ @channels.each do |n, ch|
832
+ ch.connection_closed!
833
+ ch.maybe_kill_consumer_work_pool!
823
834
  end
824
- @reader_loop.stop if @reader_loop
825
- maybe_shutdown_heartbeat_sender
835
+ end
836
+ @reader_loop.stop if @reader_loop
837
+ maybe_shutdown_heartbeat_sender
838
+
839
+ loop do
840
+ break unless recover_connection_and_channels
826
841
 
827
- recover_connection_and_channels
828
842
  recover_topology
829
- mark_channels_after_recovery!
830
- notify_of_recovery_completion
831
- else
832
- @logger.error "Exception #{exception.message} is considered unrecoverable..."
843
+
844
+ if open?
845
+ mark_channels_after_recovery!
846
+ notify_of_recovery_completion
847
+ break
848
+ end
849
+
850
+ if should_retry_recovery?
851
+ decrement_recovery_attemp_counter!
852
+ announce_network_failure_recovery
853
+ else
854
+ give_up_on_recovery
855
+ break
856
+ end
833
857
  end
834
- ensure
835
- @recovering_from_network_failure = false
858
+ else
859
+ @logger.error "Exception #{exception.message} is considered unrecoverable..."
836
860
  end
861
+ ensure
862
+ @recovery_mutex.synchronize { @recovering_from_network_failure = false }
837
863
  end
838
864
  end
839
865
 
@@ -846,7 +872,7 @@ module Bunny
846
872
  # @return [Boolean]
847
873
  # @private
848
874
  def recovering_from_network_failure?
849
- @recovering_from_network_failure
875
+ @recovery_mutex.synchronize { @recovering_from_network_failure }
850
876
  end
851
877
 
852
878
  # @param [Bunny::Queue] queue
@@ -987,7 +1013,6 @@ module Bunny
987
1013
  self.start
988
1014
 
989
1015
  if open?
990
- @recovering_from_network_failure = false
991
1016
  @logger.debug "Connection is now open"
992
1017
  if @reset_recovery_attempt_counter_after_reconnection
993
1018
  @logger.debug "Resetting recovery attempt counter after successful reconnection"
@@ -997,6 +1022,9 @@ module Bunny
997
1022
  end
998
1023
 
999
1024
  recover_channels
1025
+ true
1026
+ else
1027
+ raise TCPConnectionFailed.new("connection is not open after a connection recovery attempt", @transport.host, @transport.port)
1000
1028
  end
1001
1029
  rescue HostListDepleted
1002
1030
  reset_address_index
@@ -1010,17 +1038,23 @@ module Bunny
1010
1038
  announce_network_failure_recovery
1011
1039
  retry
1012
1040
  else
1013
- @logger.error "Ran out of recovery attempts (limit set to #{@max_recovery_attempts}), giving up"
1014
- @transport.close
1015
- self.close(false)
1016
- @manually_closed = false
1017
- notify_of_recovery_attempts_exhausted
1041
+ give_up_on_recovery
1042
+ false
1018
1043
  end
1019
1044
  else
1020
1045
  raise e
1021
1046
  end
1022
1047
  end
1023
1048
 
1049
+ # @private
1050
+ def give_up_on_recovery
1051
+ @logger.error "Ran out of recovery attempts (limit set to #{@max_recovery_attempts}), giving up"
1052
+ @transport.close
1053
+ self.close(false)
1054
+ @manually_closed = false
1055
+ notify_of_recovery_attempts_exhausted
1056
+ end
1057
+
1024
1058
  # @private
1025
1059
  def recovery_attempts_limited?
1026
1060
  !!@max_recovery_attempts
@@ -1091,7 +1125,7 @@ module Bunny
1091
1125
  exchanges.each do |x|
1092
1126
  begin
1093
1127
  recover_exchange(x)
1094
- rescue Exception => e
1128
+ rescue ::StandardError => e
1095
1129
  @logger.error "Caught an exception while recovering exchange #{x.name}: #{e.inspect}"
1096
1130
  end
1097
1131
  end
@@ -1100,7 +1134,7 @@ module Bunny
1100
1134
  queues.each do |q|
1101
1135
  begin
1102
1136
  recover_queue(q)
1103
- rescue Exception => e
1137
+ rescue ::StandardError => e
1104
1138
  @logger.error "Caught an exception while recovering queue #{q.name}: #{e.inspect}"
1105
1139
  end
1106
1140
  end
@@ -1109,7 +1143,7 @@ module Bunny
1109
1143
  queue_bindings.each do |b|
1110
1144
  begin
1111
1145
  recover_queue_binding(b)
1112
- rescue Exception => e
1146
+ rescue ::StandardError => e
1113
1147
  @logger.error "Caught an exception while recovering a binding of queue #{b.destination}: #{e.inspect}"
1114
1148
  end
1115
1149
  end
@@ -1117,14 +1151,18 @@ module Bunny
1117
1151
  exchange_bindings.each do |b|
1118
1152
  begin
1119
1153
  recover_exchange_binding(b)
1120
- rescue Exception => e
1154
+ rescue ::StandardError => e
1121
1155
  @logger.error "Caught an exception while recovering a binding of exchange #{b.source}: #{e.inspect}"
1122
1156
  end
1123
1157
  end
1124
1158
 
1125
1159
  @logger.debug { "Will recover #{consumers.size} consumer(s)" }
1126
1160
  consumers.each do |c|
1127
- recover_consumer(c)
1161
+ begin
1162
+ recover_consumer(c)
1163
+ rescue ::StandardError => e
1164
+ @logger.error "Caught an exception while recovering consumer #{c.consumer_tag} on queue #{c.queue_name}: #{e.inspect}"
1165
+ end
1128
1166
  end
1129
1167
  end
1130
1168
 
@@ -1195,8 +1233,12 @@ module Bunny
1195
1233
  # @private
1196
1234
  def recover_consumer(c)
1197
1235
  c.channel.maybe_reinitialize_consumer_pool!
1198
- c.channel.basic_consume(c.queue_name, c.consumer_tag, !c.manual_ack, c.exclusive, c.arguments) do |*args|
1199
- c.callable.call(*args)
1236
+ if c.callable.is_a?(Bunny::Consumer)
1237
+ c.channel.basic_consume_with(c.callable)
1238
+ else
1239
+ c.channel.basic_consume(c.queue_name, c.consumer_tag, !c.manual_ack, c.exclusive, c.arguments) do |*args|
1240
+ c.callable.call(*args)
1241
+ end
1200
1242
  end
1201
1243
  end
1202
1244
 
@@ -1613,9 +1655,11 @@ module Bunny
1613
1655
  # We set the read_write_timeout to twice the heartbeat value,
1614
1656
  # and then some padding for edge cases.
1615
1657
  # This allows us to miss a single heartbeat before we time out the socket.
1616
- # If heartbeats are disabled, assume that TCP keepalives or a similar mechanism will be used
1617
- # and disable socket read timeouts. See ruby-amqp/bunny#551.
1618
- @transport.read_timeout = @heartbeat * 2.2
1658
+ # If heartbeats are disabled, socket read timeouts will be disabled as well,
1659
+ # but only after negotiation completes: a peer that accepts TCP connections
1660
+ # without servicing them must not be able to block the handshake
1661
+ # indefinitely. See ruby-amqp/bunny#551.
1662
+ @transport.read_timeout = @heartbeat * 2.2 if @heartbeat > 0
1619
1663
  @logger.debug { "Will use socket read timeout of #{@transport.read_timeout.to_i} seconds" }
1620
1664
 
1621
1665
  # if there are existing channels we've just recovered from
@@ -1646,27 +1690,28 @@ module Bunny
1646
1690
  end
1647
1691
  connection_open_ok = frame2.decode_payload
1648
1692
 
1649
- @status_mutex.synchronize { @status = :open }
1650
- if @heartbeat && @heartbeat > 0
1651
- initialize_heartbeat_sender
1652
- end
1653
-
1654
1693
  unless connection_open_ok.is_a?(AMQ::Protocol::Connection::OpenOk)
1655
1694
  if connection_open_ok.is_a?(AMQ::Protocol::Connection::Close)
1656
1695
  e = instantiate_connection_level_exception(connection_open_ok)
1696
+ if automatically_recover?
1697
+ close_transport
1698
+ raise e
1699
+ end
1700
+
1657
1701
  begin
1658
1702
  shut_down_all_consumer_work_pools!
1659
1703
  maybe_shutdown_reader_loop
1660
1704
  rescue ShutdownSignal => _sse
1661
1705
  # no-op
1662
- rescue Exception => e
1663
- @logger.warn "Caught an exception when cleaning up after receiving connection.close: #{e.message}"
1706
+ rescue Exception => cleanup_exception
1707
+ @logger.warn "Caught an exception when cleaning up after receiving connection.close: #{cleanup_exception.message}"
1664
1708
  ensure
1665
1709
  close_transport
1666
1710
  end
1667
1711
 
1668
1712
  if threaded?
1669
1713
  @session_error_handler.raise(e)
1714
+ return
1670
1715
  else
1671
1716
  raise e
1672
1717
  end
@@ -1674,6 +1719,13 @@ module Bunny
1674
1719
  raise "could not open connection: server did not respond with connection.open-ok but #{connection_open_ok.inspect} instead"
1675
1720
  end
1676
1721
  end
1722
+
1723
+ @status_mutex.synchronize { @status = :open }
1724
+ if @heartbeat && @heartbeat > 0
1725
+ initialize_heartbeat_sender
1726
+ else
1727
+ @transport.read_timeout = 0
1728
+ end
1677
1729
  end
1678
1730
 
1679
1731
  def heartbeat_disabled?(val)
@@ -1714,7 +1766,7 @@ module Bunny
1714
1766
  @transport = Transport.new(self,
1715
1767
  host_from_address(address),
1716
1768
  port_from_address(address),
1717
- @opts.merge(:session_error_handler => @session_error_handler)
1769
+ @opts.merge(session_error_handler: @session_error_handler)
1718
1770
  )
1719
1771
 
1720
1772
  # Reset the cached progname for the logger only when no logger was provided
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "socket"
4
- require "thread"
5
- require "monitor"
6
4
 
7
5
  begin
8
6
  require "openssl"
@@ -305,7 +303,7 @@ module Bunny
305
303
  def self.reachable?(host, port, timeout)
306
304
  begin
307
305
  s = Bunny::SocketImpl.open(host, port,
308
- :connect_timeout => timeout)
306
+ connect_timeout: timeout)
309
307
 
310
308
  true
311
309
  rescue SocketError, Timeout::Error => _e
@@ -327,8 +325,8 @@ module Bunny
327
325
  @logger.debug("Using connection timeout of #{@connect_timeout} when connecting to #{@host}:#{@port}")
328
326
  begin
329
327
  @socket = Bunny::SocketImpl.open(@host, @port,
330
- :keepalive => @opts[:keepalive],
331
- :connect_timeout => @connect_timeout)
328
+ keepalive: @opts[:keepalive],
329
+ connect_timeout: @connect_timeout)
332
330
  rescue StandardError, ClientTimeout => e
333
331
  @status = :not_connected
334
332
  raise Bunny::TCPConnectionFailed.new(e, self.hostname, self.port)
data/lib/bunny/version.rb CHANGED
@@ -1,7 +1,6 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Bunny
5
4
  # @return [String] Version of the library
6
- VERSION = "3.1.0"
5
+ VERSION = "3.3.0"
7
6
  end
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: 3.1.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Duncan
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: '2.7'
22
+ version: '2.9'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '2.7'
29
+ version: '2.9'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: logger
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -76,6 +76,8 @@ extensions: []
76
76
  extra_rdoc_files:
77
77
  - README.md
78
78
  files:
79
+ - ChangeLog.md
80
+ - LICENSE
79
81
  - README.md
80
82
  - lib/amq/protocol/extensions.rb
81
83
  - lib/bunny.rb
@@ -134,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
136
  - !ruby/object:Gem::Version
135
137
  version: '0'
136
138
  requirements: []
137
- rubygems_version: 4.0.6
139
+ rubygems_version: 4.0.16
138
140
  specification_version: 4
139
141
  summary: Popular easy to use Ruby client for RabbitMQ
140
142
  test_files: []