bunny 2.19.0 → 2.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -32
  3. data/lib/bunny/channel.rb +86 -10
  4. data/lib/bunny/consumer.rb +2 -2
  5. data/lib/bunny/delivery_info.rb +1 -1
  6. data/lib/bunny/queue.rb +33 -2
  7. data/lib/bunny/session.rb +1 -1
  8. data/lib/bunny/transport.rb +30 -1
  9. data/lib/bunny/version.rb +1 -1
  10. data/lib/bunny.rb +45 -4
  11. metadata +4 -144
  12. data/spec/config/enabled_plugins +0 -1
  13. data/spec/config/rabbitmq.conf +0 -13
  14. data/spec/higher_level_api/integration/basic_ack_spec.rb +0 -230
  15. data/spec/higher_level_api/integration/basic_cancel_spec.rb +0 -142
  16. data/spec/higher_level_api/integration/basic_consume_spec.rb +0 -357
  17. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +0 -54
  18. data/spec/higher_level_api/integration/basic_get_spec.rb +0 -80
  19. data/spec/higher_level_api/integration/basic_nack_spec.rb +0 -82
  20. data/spec/higher_level_api/integration/basic_publish_spec.rb +0 -74
  21. data/spec/higher_level_api/integration/basic_qos_spec.rb +0 -57
  22. data/spec/higher_level_api/integration/basic_reject_spec.rb +0 -152
  23. data/spec/higher_level_api/integration/basic_return_spec.rb +0 -33
  24. data/spec/higher_level_api/integration/channel_close_spec.rb +0 -66
  25. data/spec/higher_level_api/integration/channel_open_spec.rb +0 -57
  26. data/spec/higher_level_api/integration/connection_recovery_spec.rb +0 -483
  27. data/spec/higher_level_api/integration/connection_spec.rb +0 -589
  28. data/spec/higher_level_api/integration/connection_stop_spec.rb +0 -83
  29. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +0 -128
  30. data/spec/higher_level_api/integration/dead_lettering_spec.rb +0 -75
  31. data/spec/higher_level_api/integration/exchange_bind_spec.rb +0 -31
  32. data/spec/higher_level_api/integration/exchange_declare_spec.rb +0 -237
  33. data/spec/higher_level_api/integration/exchange_delete_spec.rb +0 -105
  34. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +0 -40
  35. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +0 -28
  36. data/spec/higher_level_api/integration/heartbeat_spec.rb +0 -49
  37. data/spec/higher_level_api/integration/message_properties_access_spec.rb +0 -95
  38. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +0 -24
  39. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +0 -191
  40. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +0 -87
  41. data/spec/higher_level_api/integration/queue_bind_spec.rb +0 -109
  42. data/spec/higher_level_api/integration/queue_declare_spec.rb +0 -285
  43. data/spec/higher_level_api/integration/queue_delete_spec.rb +0 -41
  44. data/spec/higher_level_api/integration/queue_purge_spec.rb +0 -30
  45. data/spec/higher_level_api/integration/queue_unbind_spec.rb +0 -54
  46. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +0 -60
  47. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +0 -36
  48. data/spec/higher_level_api/integration/tls_connection_spec.rb +0 -255
  49. data/spec/higher_level_api/integration/toxiproxy_spec.rb +0 -76
  50. data/spec/higher_level_api/integration/tx_commit_spec.rb +0 -21
  51. data/spec/higher_level_api/integration/tx_rollback_spec.rb +0 -21
  52. data/spec/higher_level_api/integration/with_channel_spec.rb +0 -25
  53. data/spec/issues/issue100_spec.rb +0 -42
  54. data/spec/issues/issue141_spec.rb +0 -43
  55. data/spec/issues/issue202_spec.rb +0 -15
  56. data/spec/issues/issue224_spec.rb +0 -40
  57. data/spec/issues/issue465_spec.rb +0 -32
  58. data/spec/issues/issue549_spec.rb +0 -30
  59. data/spec/issues/issue609_spec.rb +0 -84
  60. data/spec/issues/issue78_spec.rb +0 -72
  61. data/spec/issues/issue83_spec.rb +0 -30
  62. data/spec/issues/issue97_attachment.json +0 -1
  63. data/spec/issues/issue97_spec.rb +0 -175
  64. data/spec/lower_level_api/integration/basic_cancel_spec.rb +0 -83
  65. data/spec/lower_level_api/integration/basic_consume_spec.rb +0 -99
  66. data/spec/spec_helper.rb +0 -47
  67. data/spec/stress/channel_close_stress_spec.rb +0 -64
  68. data/spec/stress/channel_open_stress_spec.rb +0 -84
  69. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +0 -28
  70. data/spec/stress/concurrent_consumers_stress_spec.rb +0 -71
  71. data/spec/stress/concurrent_publishers_stress_spec.rb +0 -54
  72. data/spec/stress/connection_open_close_spec.rb +0 -52
  73. data/spec/stress/merry_go_round_spec.rb +0 -105
  74. data/spec/toxiproxy_helper.rb +0 -28
  75. data/spec/unit/bunny_spec.rb +0 -15
  76. data/spec/unit/concurrent/atomic_fixnum_spec.rb +0 -35
  77. data/spec/unit/concurrent/condition_spec.rb +0 -82
  78. data/spec/unit/concurrent/linked_continuation_queue_spec.rb +0 -35
  79. data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +0 -73
  80. data/spec/unit/exchange_recovery_spec.rb +0 -39
  81. data/spec/unit/version_delivery_tag_spec.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6de535f1d386dbf46fd89a733c1c44915280af55c3cc3cc56467abe0ead9c24
4
- data.tar.gz: 6048aea84078fb8995718ed774d9a3956dc91645b24c09382cd54283b444aabe
3
+ metadata.gz: 468bfc7996c3f5788b662177b34a05347cfcb62719dcf28ed80eda672353785b
4
+ data.tar.gz: 2bdfafeb9150f68fc6dbf63fdc9b14463c0f00cb0f7a9641f1b15ddf2e4cb56e
5
5
  SHA512:
6
- metadata.gz: b3575710f81dabf6c116c92c4ac1807a29f0c0bcd1bd5fb35ae1fd9dd468df193efac49d0ad5e77ef04ecc53e97b9b4e13e70f4207972ba0c2335c28afcd6c9b
7
- data.tar.gz: 8b90dd4da7dab28b529e78cf1282656ca1904432b1017ee5574545c1972315f975d175c718481372604b61796e9ae56b293a342dcba800fa0929e4b80cd7a3c4
6
+ metadata.gz: b51c187bd404eb6a57c5ce7dd061f25de84cff1f27873e38a751269410ee46a2f639a3b94b0e4f1544c9044850df9e8db5d45fe9a35d9ba2e7bd392f2290e72b
7
+ data.tar.gz: 863c430420bc560223e24e90fb259bfc537ef73c016b2089e14d1b73307f8564cf945ade393d36b0cfe4a259b4daec88f50ee12d0a6cb037d27ce5aab0466d64
data/README.md CHANGED
@@ -7,7 +7,7 @@ have any heavyweight dependencies.
7
7
 
8
8
  ## I Know What RabbitMQ and Bunny are, How Do I Get Started?
9
9
 
10
- [Right here](http://rubybunny.info/articles/getting_started.html)!
10
+ [Right here](https://www.rabbitmq.com/getstarted.html)!
11
11
 
12
12
 
13
13
  ## What is Bunny Good For?
@@ -47,7 +47,8 @@ Specific examples:
47
47
 
48
48
  Modern Bunny versions support
49
49
 
50
- * CRuby 2.5 through 3.0 (inclusive)
50
+ * CRuby 2.6 through 3.1 (inclusive)
51
+ * [TruffleRuby](https://www.graalvm.org/ruby/)
51
52
 
52
53
  Bunny works sufficiently well on JRuby but there are known
53
54
  JRuby bugs in versions prior to JRuby 9000 that cause high CPU burn. JRuby users should
@@ -58,8 +59,7 @@ Bunny `1.7.x` was the last version to support CRuby 1.9.3 and 1.8.7
58
59
 
59
60
  ## Supported RabbitMQ Versions
60
61
 
61
- Bunny `1.5.0` and later versions only support RabbitMQ `3.3+`.
62
- Bunny `1.4.x` and earlier supports RabbitMQ 2.x and 3.x.
62
+ Modern Bunny releases target [currently supported RabbitMQ release series](https://www.rabbitmq.com/versions.html).
63
63
 
64
64
 
65
65
  ## Change Log
@@ -69,9 +69,8 @@ a stable public API.
69
69
 
70
70
  Change logs per release series:
71
71
 
72
- * [master](https://github.com/ruby-amqp/bunny/blob/master/ChangeLog.md)
73
- * [2.18.x](https://github.com/ruby-amqp/bunny/blob/2.18.x-stable/ChangeLog.md)
74
- * [2.17.x](https://github.com/ruby-amqp/bunny/blob/2.17.x-stable/ChangeLog.md)
72
+ * [main](https://github.com/ruby-amqp/bunny/blob/main/ChangeLog.md) (most notable changes for all release series)
73
+ * [2.19.x](https://github.com/ruby-amqp/bunny/blob/2.19.x-stable/ChangeLog.md)
75
74
 
76
75
 
77
76
 
@@ -81,20 +80,20 @@ Change logs per release series:
81
80
 
82
81
  [![Gem Version](https://badge.fury.io/rb/bunny.svg)](http://badge.fury.io/rb/bunny)
83
82
 
84
- ### With Rubygems
83
+ ### Bundler Dependency
85
84
 
86
- To install Bunny with RubyGems:
85
+ To use Bunny in a project managed with Bundler:
87
86
 
88
- ```
89
- gem install bunny
87
+ ``` ruby
88
+ gem "bunny", ">= 2.19.0"
90
89
  ```
91
90
 
92
- ### Bundler Dependency
91
+ ### With Rubygems
93
92
 
94
- To use Bunny in a project managed with Bundler:
93
+ To install Bunny with RubyGems:
95
94
 
96
- ``` ruby
97
- gem "bunny", ">= 2.18.0"
95
+ ```
96
+ gem install bunny
98
97
  ```
99
98
 
100
99
 
@@ -103,7 +102,7 @@ gem "bunny", ">= 2.18.0"
103
102
  Below is a small snippet that demonstrates how to publish
104
103
  and synchronously consume ("pull API") messages with Bunny.
105
104
 
106
- For a 15 minute tutorial using more practical examples, see [Getting Started with RabbitMQ and Ruby using Bunny](http://rubybunny.info/articles/getting_started.html).
105
+ For a 15 minute tutorial using more practical examples, see [Getting Started with RabbitMQ and Ruby using Bunny](https://www.rabbitmq.com/tutorials/tutorial-one-ruby.html).
107
106
 
108
107
  ``` ruby
109
108
  require "bunny"
@@ -150,23 +149,25 @@ For a 15 minute tutorial using more practical examples, see [Getting Started wit
150
149
 
151
150
  ### Guides
152
151
 
153
- Bunny documentation guides are available at [rubybunny.info](http://rubybunny.info):
152
+ Bunny documentation guides are [under `docs/guides` in this repository](https://github.com/ruby-amqp/bunny/tree/main/docs/guides):
154
153
 
155
- * [Queues and Consumers](http://rubybunny.info/articles/queues.html)
156
- * [Exchanges and Publishers](http://rubybunny.info/articles/exchanges.html)
154
+ * [Queues and Consumers](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/queues.md)
155
+ * [Exchanges and Publishers](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/exchanges.md)
157
156
  * [AMQP 0.9.1 Model Explained](http://www.rabbitmq.com/tutorials/amqp-concepts.html)
158
- * [Connecting to RabbitMQ](http://rubybunny.info/articles/connecting.html)
159
- * [Error Handling and Recovery](http://rubybunny.info/articles/error_handling.html)
160
- * [TLS/SSL Support](http://rubybunny.info/articles/tls.html)
161
- * [Bindings](http://rubybunny.info/articles/bindings.html)
162
- * [Using RabbitMQ Extensions with Bunny](http://rubybunny.info/articles/extensions.html)
163
- * [Durability and Related Matters](http://rubybunny.info/articles/durability.html)
157
+ * [Connecting to RabbitMQ](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/connecting.md)
158
+ * [Error Handling and Recovery](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/error_handling.md)
159
+ * [TLS/SSL Support](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/tls.md)
160
+ * [Bindings](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/bindings.md)
161
+ * [Using RabbitMQ Extensions with Bunny](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/extensions.md)
162
+ * [Durability and Related Matters](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/durability.md)
164
163
 
165
164
  Some highly relevant RabbitMQ documentation guides:
166
165
 
167
166
  * [Connections](https://www.rabbitmq.com/connections.html)
168
167
  * [Channels](https://www.rabbitmq.com/channels.html)
169
168
  * [Queues](https://www.rabbitmq.com/queues.html)
169
+ * [Quorum queues](https://www.rabbitmq.com/quorum-queues.html)
170
+ * [Streams](https://rabbitmq.com/streams.html) (Bunny can perform basic operations on streams even though it does not implement the [RabbitMQ Stream protocol](https://github.com/rabbitmq/rabbitmq-server/blob/v3.10.x/deps/rabbitmq_stream/docs/PROTOCOL.adoc))
170
171
  * [Publishers](https://www.rabbitmq.com/publishers.html)
171
172
  * [Consumers](https://www.rabbitmq.com/consumers.html)
172
173
  * Data safety: publisher and consumer [Confirmations](https://www.rabbitmq.com/confirms.html)
@@ -194,13 +195,6 @@ mailing list. Feel free to ask any questions that you may have.
194
195
  [![Build Status](https://travis-ci.org/ruby-amqp/bunny.svg)](https://travis-ci.org/ruby-amqp/bunny/)
195
196
 
196
197
 
197
- ### News & Announcements on Twitter
198
-
199
- To subscribe for announcements of releases, important changes and so on, please follow [@rubyamqp](https://twitter.com/#!/rubyamqp) on Twitter.
200
-
201
- More detailed announcements can be found in the [RabbitMQ Ruby clients blog](http://blog.rubyrabbitmq.info).
202
-
203
-
204
198
  ### Reporting Issues
205
199
 
206
200
  If you find a bug you understand well, poor default, incorrect or unclear piece of documentation,
data/lib/bunny/channel.rb CHANGED
@@ -143,6 +143,10 @@ module Bunny
143
143
  attr_reader :work_pool
144
144
  # @return [Integer] Next publisher confirmations sequence index
145
145
  attr_reader :next_publish_seq_no
146
+ # @return [Integer] Offset for the confirmations sequence index.
147
+ # This will be set to the current sequence index during automatic network failure recovery
148
+ # to keep the sequence monotonic for the user and abstract the reset from the protocol
149
+ attr_reader :delivery_tag_offset
146
150
  # @return [Hash<String, Bunny::Queue>] Queue instances declared on this channel
147
151
  attr_reader :queues
148
152
  # @return [Hash<String, Bunny::Exchange>] Exchange instances declared on this channel
@@ -408,7 +412,7 @@ module Bunny
408
412
  # @option opts [Boolean] :durable (false) Should this queue be durable?
409
413
  # @option opts [Boolean] :auto-delete (false) Should this queue be automatically deleted when the last consumer disconnects?
410
414
  # @option opts [Boolean] :exclusive (false) Should this queue be exclusive (only can be used by this connection, removed when the connection is closed)?
411
- # @option opts [Boolean] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
415
+ # @option opts [Hash] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
412
416
  #
413
417
  # @return [Bunny::Queue] Queue that was declared or looked up in the cache
414
418
  # @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
@@ -422,6 +426,73 @@ module Bunny
422
426
  register_queue(q)
423
427
  end
424
428
 
429
+ # Declares a new client-named quorum queue.
430
+ #
431
+ # @param [String] name Queue name. Empty (server-generated) names are not supported by this method.
432
+ # @param [Hash] opts Queue properties and other options. Durability, exclusivity, auto-deletion options will be ignored.
433
+ #
434
+ # @option opts [Hash] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
435
+ #
436
+ # @return [Bunny::Queue] Queue that was declared
437
+ # @see #durable_queue
438
+ # @see #queue
439
+ # @api public
440
+ def quorum_queue(name, opts = {})
441
+ throw ArgumentError.new("quorum queue name must not be nil") if name.nil?
442
+ throw ArgumentError.new("quorum queue name must not be empty (server-named QQs do not make sense)") if name.empty?
443
+
444
+ durable_queue(name, Bunny::Queue::Types::QUORUM, opts)
445
+ end
446
+
447
+ # Declares a new client-named stream (that Bunny can use as if it was a queue).
448
+ # Note that Bunny would still use AMQP 0-9-1 to perform operations on this "queue".
449
+ # To use stream-specific operations and to gain from stream protocol efficiency and partitioning,
450
+ # use a Ruby client for the RabbitMQ stream protocol.
451
+ #
452
+ # @param [String] name Stream name. Empty (server-generated) names are not supported by this method.
453
+ # @param [Hash] opts Queue properties and other options. Durability, exclusivity, auto-deletion options will be ignored.
454
+ #
455
+ # @option opts [Hash] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
456
+ #
457
+ #
458
+ # @return [Bunny::Queue] Queue that was declared
459
+ # @see #durable_queue
460
+ # @see #queue
461
+ # @api public
462
+ def stream(name, opts = {})
463
+ throw ArgumentError.new("stream name must not be nil") if name.nil?
464
+ throw ArgumentError.new("stream name must not be empty (server-named QQs do not make sense)") if name.empty?
465
+
466
+ durable_queue(name, Bunny::Queue::Types::STREAM, opts)
467
+ end
468
+
469
+ # Declares a new server-named queue that is automatically deleted when the
470
+ # connection is closed.
471
+ #
472
+ # @param [String] name Queue name. Empty (server-generated) names are not supported by this method.
473
+ # @param [Hash] opts Queue properties and other options. Durability, exclusivity, auto-deletion options will be ignored.
474
+ #
475
+ # @option opts [Hash] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
476
+ #
477
+ # @return [Bunny::Queue] Queue that was declared
478
+ # @see #queue
479
+ # @api public
480
+ def durable_queue(name, type = "classic", opts = {})
481
+ throw ArgumentError.new("queue name must not be nil") if name.nil?
482
+ throw ArgumentError.new("queue name must not be empty (server-named durable queues do not make sense)") if name.empty?
483
+
484
+ final_opts = opts.merge({
485
+ :type => type,
486
+ :durable => true,
487
+ # exclusive or auto-delete QQs do not make much sense
488
+ :exclusive => false,
489
+ :auto_delete => false
490
+ })
491
+ q = find_queue(name) || Bunny::Queue.new(self, name, final_opts)
492
+
493
+ register_queue(q)
494
+ end
495
+
425
496
  # Declares a new server-named queue that is automatically deleted when the
426
497
  # connection is closed.
427
498
  #
@@ -1525,12 +1596,15 @@ module Bunny
1525
1596
 
1526
1597
  # Recovers publisher confirms mode. Used by the Automatic Network Failure
1527
1598
  # Recovery feature.
1599
+ # Set the offset to the previous publish sequence index as the protocol will reset the index to after recovery.
1528
1600
  #
1529
1601
  # @api plugin
1530
1602
  def recover_confirm_mode
1531
1603
  if using_publisher_confirmations?
1532
- @unconfirmed_set.clear
1533
- @delivery_tag_offset = @next_publish_seq_no - 1
1604
+ @unconfirmed_set_mutex.synchronize do
1605
+ @unconfirmed_set.clear
1606
+ @delivery_tag_offset = @next_publish_seq_no - 1
1607
+ end
1534
1608
  confirm_select(@confirms_callback)
1535
1609
  end
1536
1610
  end
@@ -1599,7 +1673,7 @@ module Bunny
1599
1673
 
1600
1674
  # @return [String] Brief human-readable representation of the channel
1601
1675
  def to_s
1602
- "#<#{self.class.name}:#{object_id} @id=#{self.number} @connection=#{@connection.to_s}> @open=#{open?}"
1676
+ "#<#{self.class.name}:#{object_id} @id=#{self.number} @connection=#{@connection.to_s} @open=#{open?}>"
1603
1677
  end
1604
1678
 
1605
1679
  def inspect
@@ -1663,7 +1737,7 @@ module Bunny
1663
1737
  if !pending_server_named_queue_declaration?
1664
1738
  # this response is for an outdated/overwritten
1665
1739
  # queue.declare, drop it
1666
- @logger.warn "Received a queue.declare-ok response for a mismatching queue (#{method.queue} instead of #{@pending_queue_declare_name}) on channel #{@id} possibly due to a timeout, ignoring it"
1740
+ @logger.warn "Received a queue.declare-ok response for a mismatching queue (#{method.queue} instead of #{@pending_queue_declare_name}) on channel #{@id}, possibly due to concurrent channel use or a timeout, ignoring it"
1667
1741
  end
1668
1742
  end
1669
1743
  when AMQ::Protocol::Queue::DeleteOk then
@@ -1786,14 +1860,16 @@ module Bunny
1786
1860
  end
1787
1861
  end
1788
1862
 
1863
+ # Handle delivery tag offset calculations to keep the the delivery tag monotonic after a reset
1864
+ # due to automatic network failure recovery. @unconfirmed_set contains indices already offsetted.
1789
1865
  # @private
1790
1866
  def handle_ack_or_nack(delivery_tag_before_offset, multiple, nack)
1791
- delivery_tag = delivery_tag_before_offset + @delivery_tag_offset
1792
- confirmed_range_start = multiple ? @delivery_tag_offset + @unconfirmed_set.min : delivery_tag
1793
- confirmed_range_end = delivery_tag
1794
- confirmed_range = (confirmed_range_start..confirmed_range_end)
1795
-
1796
1867
  @unconfirmed_set_mutex.synchronize do
1868
+ delivery_tag = delivery_tag_before_offset + @delivery_tag_offset
1869
+ confirmed_range_start = multiple ? @unconfirmed_set.min : delivery_tag
1870
+ confirmed_range_end = delivery_tag
1871
+ confirmed_range = (confirmed_range_start..confirmed_range_end)
1872
+
1797
1873
  if nack
1798
1874
  @nacked_set.merge(@unconfirmed_set & confirmed_range)
1799
1875
  end
@@ -86,12 +86,12 @@ module Bunny
86
86
 
87
87
  # @return [String] More detailed human-readable string representation of this consumer
88
88
  def inspect
89
- "#<#{self.class.name}:#{object_id} @channel_id=#{@channel.number} @queue=#{self.queue_name}> @consumer_tag=#{@consumer_tag} @exclusive=#{@exclusive} @no_ack=#{@no_ack}>"
89
+ "#<#{self.class.name}:#{object_id} @channel_id=#{@channel.number} @queue=#{self.queue_name} @consumer_tag=#{@consumer_tag} @exclusive=#{@exclusive} @no_ack=#{@no_ack}>"
90
90
  end
91
91
 
92
92
  # @return [String] Brief human-readable string representation of this consumer
93
93
  def to_s
94
- "#<#{self.class.name}:#{object_id} @channel_id=#{@channel.number} @queue=#{self.queue_name}> @consumer_tag=#{@consumer_tag}>"
94
+ "#<#{self.class.name}:#{object_id} @channel_id=#{@channel.number} @queue=#{self.queue_name} @consumer_tag=#{@consumer_tag}>"
95
95
  end
96
96
 
97
97
  # @return [Boolean] true if this consumer uses automatic acknowledgement mode
@@ -37,7 +37,7 @@ module Bunny
37
37
  @channel = channel
38
38
  end
39
39
 
40
- # Iterates over the delivery properties
40
+ # Iterates over delivery properties
41
41
  # @see Enumerable#each
42
42
  def each(*args, &block)
43
43
  @hash.each(*args, &block)
data/lib/bunny/queue.rb CHANGED
@@ -11,6 +11,23 @@ module Bunny
11
11
  # API
12
12
  #
13
13
 
14
+ module Types
15
+ QUORUM = "quorum"
16
+ CLASSIC = "classic"
17
+ STREAM = "stream"
18
+
19
+ KNOWN = [CLASSIC, QUORUM, STREAM]
20
+
21
+ def self.known?(q_type)
22
+ KNOWN.include?(q_type)
23
+ end
24
+ end
25
+
26
+ module XArgs
27
+ MAX_LENGTH = "x-max-length",
28
+ QUEUE_TYPE = "x-queue-type"
29
+ end
30
+
14
31
  # @return [Bunny::Channel] Channel this queue uses
15
32
  attr_reader :channel
16
33
  # @return [String] Queue name
@@ -25,7 +42,8 @@ module Bunny
25
42
  # @option opts [Boolean] :durable (false) Should this queue be durable?
26
43
  # @option opts [Boolean] :auto_delete (false) Should this queue be automatically deleted when the last consumer disconnects?
27
44
  # @option opts [Boolean] :exclusive (false) Should this queue be exclusive (only can be used by this connection, removed when the connection is closed)?
28
- # @option opts [Boolean] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
45
+ # @option opts [String] :type (nil) Type of the declared queue (classic, quorum or stream)
46
+ # @option opts [Hash] :arguments (nil) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
29
47
  #
30
48
  # @see Bunny::Channel#queue
31
49
  # @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
@@ -42,7 +60,14 @@ module Bunny
42
60
  @exclusive = @options[:exclusive]
43
61
  @server_named = @name.empty?
44
62
  @auto_delete = @options[:auto_delete]
45
- @arguments = @options[:arguments]
63
+ @type = @options[:type]
64
+
65
+ @arguments = if @type and !@type.empty? then
66
+ (@options[:arguments] || {}).merge({XArgs::QUEUE_TYPE => @type})
67
+ else
68
+ @options[:arguments]
69
+ end
70
+ verify_type!(@arguments)
46
71
 
47
72
  @bindings = Array.new
48
73
 
@@ -389,5 +414,11 @@ module Bunny
389
414
  h
390
415
  end
391
416
  end
417
+
418
+ def verify_type!(args)
419
+ q_type = (args || {})["x-queue-type"]
420
+ throw ArgumentError.new(
421
+ "unsupported queue type #{q_type.inspect}, supported ones: #{Types::KNOWN.join(', ')}") if (q_type and !Types.known?(q_type))
422
+ end
392
423
  end
393
424
  end
data/lib/bunny/session.rb CHANGED
@@ -109,7 +109,7 @@ module Bunny
109
109
  # @option connection_string_or_opts [String] :tls_key (nil) Path to client TLS/SSL private key file (.pem)
110
110
  # @option connection_string_or_opts [Array<String>] :tls_ca_certificates Array of paths to TLS/SSL CA files (.pem), by default detected from OpenSSL configuration
111
111
  # @option connection_string_or_opts [String] :verify_peer (true) Whether TLS peer verification should be performed
112
- # @option connection_string_or_opts [Symbol] :tls_version (negotiated) What TLS version should be used (:TLSv1, :TLSv1_1, or :TLSv1_2)
112
+ # @option connection_string_or_opts [Symbol] :tls_protocol (negotiated) What TLS version should be used (:TLSv1, :TLSv1_1, or :TLSv1_2)
113
113
  # @option connection_string_or_opts [Integer] :channel_max (2047) Maximum number of channels allowed on this connection, minus 1 to account for the special channel 0.
114
114
  # @option connection_string_or_opts [Integer] :continuation_timeout (15000) Timeout for client operations that expect a response (e.g. {Bunny::Queue#get}), in milliseconds.
115
115
  # @option connection_string_or_opts [Integer] :connection_timeout (30) Timeout in seconds for connecting to the server.
@@ -25,6 +25,23 @@ module Bunny
25
25
  DEFAULT_READ_TIMEOUT = 30.0
26
26
  DEFAULT_WRITE_TIMEOUT = 30.0
27
27
 
28
+ # mimics METHODS_MAP in ssl.rb but also lists TLS 1.3
29
+ # and string constants
30
+ TLS_VERSION_ALIASES = {
31
+ TLSv1: OpenSSL::SSL::TLS1_VERSION,
32
+ TLSv1_1: OpenSSL::SSL::TLS1_1_VERSION,
33
+ TLSv1_2: OpenSSL::SSL::TLS1_2_VERSION,
34
+ TLSv1_3: OpenSSL::SSL::TLS1_3_VERSION,
35
+ "1.0": OpenSSL::SSL::TLS1_VERSION,
36
+ "1.1": OpenSSL::SSL::TLS1_1_VERSION,
37
+ "1.2": OpenSSL::SSL::TLS1_2_VERSION,
38
+ "1.3": OpenSSL::SSL::TLS1_3_VERSION,
39
+ OpenSSL::SSL::TLS1_VERSION => OpenSSL::SSL::TLS1_VERSION,
40
+ OpenSSL::SSL::TLS1_1_VERSION => OpenSSL::SSL::TLS1_1_VERSION,
41
+ OpenSSL::SSL::TLS1_2_VERSION => OpenSSL::SSL::TLS1_2_VERSION,
42
+ OpenSSL::SSL::TLS1_3_VERSION => OpenSSL::SSL::TLS1_3_VERSION
43
+ }.freeze
44
+
28
45
  attr_reader :session, :host, :port, :socket, :connect_timeout, :read_timeout, :write_timeout, :disconnect_timeout
29
46
  attr_reader :tls_context, :verify_peer, :tls_ca_certificates, :tls_certificate_path, :tls_key_path
30
47
 
@@ -491,7 +508,11 @@ but prone to man-in-the-middle attacks. Please set verify_peer: true in producti
491
508
  end
492
509
 
493
510
  ssl_version = opts[:tls_protocol] || opts[:ssl_version] || :TLSv1_2
494
- ctx.ssl_version = ssl_version if ssl_version
511
+ if ssl_version
512
+ v = tls_version_constant(ssl_version)
513
+ ctx.min_version = v
514
+ ctx.max_version = v
515
+ end
495
516
 
496
517
  ctx
497
518
  end
@@ -519,6 +540,14 @@ but prone to man-in-the-middle attacks. Please set verify_peer: true in producti
519
540
  end
520
541
  end
521
542
 
543
+
544
+ def tls_version_constant(value)
545
+ # OpenSSL::SSL::TLS1_3_VERSION and similar constants
546
+ # are just integers, so use the value itself as fallback since
547
+ # there is no class to case switch on
548
+ TLS_VERSION_ALIASES[value] || value
549
+ end
550
+
522
551
  def timeout_from(options)
523
552
  options[:connect_timeout] || options[:connection_timeout] || options[:timeout] || DEFAULT_CONNECTION_TIMEOUT
524
553
  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.19.0"
5
+ VERSION = "2.20.0"
6
6
  end
data/lib/bunny.rb CHANGED
@@ -53,17 +53,58 @@ module Bunny
53
53
  # Instantiates a new connection. The actual network
54
54
  # connection is started with {Bunny::Session#start}
55
55
  #
56
+ # @param [String, Hash] connection_string_or_opts Connection string or a hash of connection options
57
+ # @param [Hash] optz Extra options not related to connection
58
+ #
59
+ # @option connection_string_or_opts [String] :host ("127.0.0.1") Hostname or IP address to connect to
60
+ # @option connection_string_or_opts [Array<String>] :hosts (["127.0.0.1"]) list of hostname or IP addresses to select hostname from when connecting
61
+ # @option connection_string_or_opts [Array<String>] :addresses (["127.0.0.1:5672"]) list of addresses to select hostname and port from when connecting
62
+ # @option connection_string_or_opts [Integer] :port (5672) Port RabbitMQ listens on
63
+ # @option connection_string_or_opts [String] :username ("guest") Username
64
+ # @option connection_string_or_opts [String] :password ("guest") Password
65
+ # @option connection_string_or_opts [String] :vhost ("/") Virtual host to use
66
+ # @option connection_string_or_opts [Integer, Symbol] :heartbeat (:server) Heartbeat timeout to offer to the server. :server means use the value suggested by RabbitMQ. 0 means heartbeats and socket read timeouts will be disabled (not recommended).
67
+ # @option connection_string_or_opts [Integer] :network_recovery_interval (4) Recovery interval periodic network recovery will use. This includes initial pause after network failure.
68
+ # @option connection_string_or_opts [Boolean] :tls (false) Should TLS/SSL be used?
69
+ # @option connection_string_or_opts [String] :tls_cert (nil) Path to client TLS/SSL certificate file (.pem)
70
+ # @option connection_string_or_opts [String] :tls_key (nil) Path to client TLS/SSL private key file (.pem)
71
+ # @option connection_string_or_opts [Array<String>] :tls_ca_certificates Array of paths to TLS/SSL CA files (.pem), by default detected from OpenSSL configuration
72
+ # @option connection_string_or_opts [String] :verify_peer (true) Whether TLS peer verification should be performed
73
+ # @option connection_string_or_opts [Symbol] :tls_protocol (negotiated) What TLS version should be used (:TLSv1, :TLSv1_1, or :TLSv1_2)
74
+ # @option connection_string_or_opts [Integer] :channel_max (2047) Maximum number of channels allowed on this connection, minus 1 to account for the special channel 0.
75
+ # @option connection_string_or_opts [Integer] :continuation_timeout (15000) Timeout for client operations that expect a response (e.g. {Bunny::Queue#get}), in milliseconds.
76
+ # @option connection_string_or_opts [Integer] :connection_timeout (30) Timeout in seconds for connecting to the server.
77
+ # @option connection_string_or_opts [Integer] :read_timeout (30) TCP socket read timeout in seconds. If heartbeats are disabled this will be ignored.
78
+ # @option connection_string_or_opts [Integer] :write_timeout (30) TCP socket write timeout in seconds.
79
+ # @option connection_string_or_opts [Proc] :hosts_shuffle_strategy a callable that reorders a list of host strings, defaults to Array#shuffle
80
+ # @option connection_string_or_opts [Proc] :recovery_completed a callable that will be called when a network recovery is performed
81
+ # @option connection_string_or_opts [Logger] :logger The logger. If missing, one is created using :log_file and :log_level.
82
+ # @option connection_string_or_opts [IO, String] :log_file The file or path to use when creating a logger. Defaults to STDOUT.
83
+ # @option connection_string_or_opts [IO, String] :logfile DEPRECATED: use :log_file instead. The file or path to use when creating a logger. Defaults to STDOUT.
84
+ # @option connection_string_or_opts [Integer] :log_level The log level to use when creating a logger. Defaults to LOGGER::WARN
85
+ # @option connection_string_or_opts [Boolean] :automatically_recover (true) Should automatically recover from network failures?
86
+ # @option connection_string_or_opts [Integer] :recovery_attempts (nil) Max number of recovery attempts, nil means forever
87
+ # @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.
88
+ # @option connection_string_or_opts [Proc] :recovery_attempt_started (nil) Will be called before every connection recovery attempt
89
+ # @option connection_string_or_opts [Proc] :recovery_completed (nil) Will be called after successful connection recovery
90
+ # @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)?
91
+ # @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.
92
+ #
93
+ # @option optz [String] :auth_mechanism ("PLAIN") Authentication mechanism, PLAIN or EXTERNAL
94
+ # @option optz [String] :locale ("PLAIN") Locale RabbitMQ should use
95
+ # @option optz [String] :connection_name (nil) Client-provided connection name, if any. Note that the value returned does not uniquely identify a connection and cannot be used as a connection identifier in HTTP API requests.
96
+ #
56
97
  # @return [Bunny::Session]
57
98
  # @see Bunny::Session#start
58
99
  # @see http://rubybunny.info/articles/getting_started.html
59
100
  # @see http://rubybunny.info/articles/connecting.html
60
101
  # @api public
61
- def self.new(connection_string_or_opts = ENV['RABBITMQ_URL'], opts = {})
62
- if connection_string_or_opts.respond_to?(:keys) && opts.empty?
63
- opts = connection_string_or_opts
102
+ def self.new(connection_string_or_opts = ENV['RABBITMQ_URL'], optz = {})
103
+ if connection_string_or_opts.respond_to?(:keys) && optz.empty?
104
+ optz = connection_string_or_opts
64
105
  end
65
106
 
66
- conn = Session.new(connection_string_or_opts, opts)
107
+ conn = Session.new(connection_string_or_opts, optz)
67
108
  @default_connection ||= conn
68
109
 
69
110
  conn