bunny 2.14.2 → 2.22.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 +4 -4
- data/README.md +56 -39
- data/lib/bunny/channel.rb +89 -13
- data/lib/bunny/consumer.rb +2 -2
- data/lib/bunny/consumer_work_pool.rb +1 -1
- data/lib/bunny/cruby/socket.rb +3 -0
- data/lib/bunny/delivery_info.rb +1 -1
- data/lib/bunny/queue.rb +36 -5
- data/lib/bunny/reader_loop.rb +21 -13
- data/lib/bunny/session.rb +83 -25
- data/lib/bunny/transport.rb +49 -12
- data/lib/bunny/version.rb +1 -1
- data/lib/bunny.rb +45 -4
- metadata +37 -235
- data/.github/ISSUE_TEMPLATE.md +0 -18
- data/.gitignore +0 -28
- data/.rspec +0 -1
- data/.travis.yml +0 -31
- data/.yardopts +0 -8
- data/CONTRIBUTING.md +0 -132
- data/ChangeLog.md +0 -2072
- data/Gemfile +0 -55
- data/LICENSE +0 -21
- data/Rakefile +0 -54
- data/benchmarks/basic_publish/with_128K_messages.rb +0 -35
- data/benchmarks/basic_publish/with_1k_messages.rb +0 -35
- data/benchmarks/basic_publish/with_4K_messages.rb +0 -35
- data/benchmarks/basic_publish/with_64K_messages.rb +0 -35
- data/benchmarks/channel_open.rb +0 -28
- data/benchmarks/mutex_and_monitor.rb +0 -42
- data/benchmarks/queue_declare.rb +0 -29
- data/benchmarks/queue_declare_and_bind.rb +0 -29
- data/benchmarks/queue_declare_bind_and_delete.rb +0 -29
- data/benchmarks/synchronized_sorted_set.rb +0 -53
- data/benchmarks/write_vs_write_nonblock.rb +0 -49
- data/bunny.gemspec +0 -34
- data/docker/Dockerfile +0 -20
- data/docker/apt/preferences.d/erlang +0 -3
- data/docker/apt/sources.list.d/bintray.rabbitmq.list +0 -2
- data/docker/docker-entrypoint.sh +0 -26
- data/docker/rabbitmq.conf +0 -29
- data/docker-compose.yml +0 -28
- data/examples/connection/authentication_failure.rb +0 -16
- data/examples/connection/automatic_recovery_with_basic_get.rb +0 -40
- data/examples/connection/automatic_recovery_with_client_named_queues.rb +0 -36
- data/examples/connection/automatic_recovery_with_multiple_consumers.rb +0 -46
- data/examples/connection/automatic_recovery_with_republishing.rb +0 -109
- data/examples/connection/automatic_recovery_with_server_named_queues.rb +0 -35
- data/examples/connection/channel_level_exception.rb +0 -27
- data/examples/connection/disabled_automatic_recovery.rb +0 -34
- data/examples/connection/heartbeat.rb +0 -17
- data/examples/connection/manually_reconnecting_consumer.rb +0 -23
- data/examples/connection/manually_reconnecting_publisher.rb +0 -28
- data/examples/connection/unknown_host.rb +0 -16
- data/examples/consumers/high_and_low_priority.rb +0 -50
- data/examples/guides/exchanges/direct_exchange_routing.rb +0 -36
- data/examples/guides/exchanges/fanout_exchange_routing.rb +0 -28
- data/examples/guides/exchanges/headers_exchange_routing.rb +0 -31
- data/examples/guides/exchanges/mandatory_messages.rb +0 -30
- data/examples/guides/extensions/alternate_exchange.rb +0 -30
- data/examples/guides/extensions/basic_nack.rb +0 -33
- data/examples/guides/extensions/connection_blocked.rb +0 -35
- data/examples/guides/extensions/consumer_cancellation_notification.rb +0 -39
- data/examples/guides/extensions/dead_letter_exchange.rb +0 -32
- data/examples/guides/extensions/exchange_to_exchange_bindings.rb +0 -29
- data/examples/guides/extensions/per_message_ttl.rb +0 -36
- data/examples/guides/extensions/per_queue_message_ttl.rb +0 -36
- data/examples/guides/extensions/publisher_confirms.rb +0 -28
- data/examples/guides/extensions/queue_lease.rb +0 -26
- data/examples/guides/extensions/sender_selected_distribution.rb +0 -32
- data/examples/guides/getting_started/blabbr.rb +0 -27
- data/examples/guides/getting_started/hello_world.rb +0 -22
- data/examples/guides/getting_started/weathr.rb +0 -49
- data/examples/guides/queues/one_off_consumer.rb +0 -25
- data/examples/guides/queues/redeliveries.rb +0 -81
- data/profiling/basic_publish/with_4K_messages.rb +0 -33
- data/repl +0 -3
- data/spec/config/enabled_plugins +0 -1
- data/spec/config/rabbitmq.conf +0 -13
- data/spec/higher_level_api/integration/basic_ack_spec.rb +0 -230
- data/spec/higher_level_api/integration/basic_cancel_spec.rb +0 -142
- data/spec/higher_level_api/integration/basic_consume_spec.rb +0 -349
- data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +0 -54
- data/spec/higher_level_api/integration/basic_get_spec.rb +0 -80
- data/spec/higher_level_api/integration/basic_nack_spec.rb +0 -82
- data/spec/higher_level_api/integration/basic_publish_spec.rb +0 -74
- data/spec/higher_level_api/integration/basic_qos_spec.rb +0 -57
- data/spec/higher_level_api/integration/basic_reject_spec.rb +0 -152
- data/spec/higher_level_api/integration/basic_return_spec.rb +0 -33
- data/spec/higher_level_api/integration/channel_close_spec.rb +0 -66
- data/spec/higher_level_api/integration/channel_open_spec.rb +0 -57
- data/spec/higher_level_api/integration/connection_recovery_spec.rb +0 -483
- data/spec/higher_level_api/integration/connection_spec.rb +0 -563
- data/spec/higher_level_api/integration/connection_stop_spec.rb +0 -83
- data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +0 -128
- data/spec/higher_level_api/integration/dead_lettering_spec.rb +0 -75
- data/spec/higher_level_api/integration/exchange_bind_spec.rb +0 -31
- data/spec/higher_level_api/integration/exchange_declare_spec.rb +0 -237
- data/spec/higher_level_api/integration/exchange_delete_spec.rb +0 -105
- data/spec/higher_level_api/integration/exchange_unbind_spec.rb +0 -40
- data/spec/higher_level_api/integration/exclusive_queue_spec.rb +0 -28
- data/spec/higher_level_api/integration/heartbeat_spec.rb +0 -49
- data/spec/higher_level_api/integration/message_properties_access_spec.rb +0 -95
- data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +0 -24
- data/spec/higher_level_api/integration/publisher_confirms_spec.rb +0 -191
- data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +0 -87
- data/spec/higher_level_api/integration/queue_bind_spec.rb +0 -109
- data/spec/higher_level_api/integration/queue_declare_spec.rb +0 -285
- data/spec/higher_level_api/integration/queue_delete_spec.rb +0 -41
- data/spec/higher_level_api/integration/queue_purge_spec.rb +0 -30
- data/spec/higher_level_api/integration/queue_unbind_spec.rb +0 -54
- data/spec/higher_level_api/integration/read_only_consumer_spec.rb +0 -60
- data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +0 -36
- data/spec/higher_level_api/integration/tls_connection_spec.rb +0 -250
- data/spec/higher_level_api/integration/toxiproxy_spec.rb +0 -76
- data/spec/higher_level_api/integration/tx_commit_spec.rb +0 -21
- data/spec/higher_level_api/integration/tx_rollback_spec.rb +0 -21
- data/spec/higher_level_api/integration/with_channel_spec.rb +0 -25
- data/spec/issues/issue100_spec.rb +0 -42
- data/spec/issues/issue141_spec.rb +0 -43
- data/spec/issues/issue202_spec.rb +0 -15
- data/spec/issues/issue224_spec.rb +0 -40
- data/spec/issues/issue465_spec.rb +0 -32
- data/spec/issues/issue549_spec.rb +0 -30
- data/spec/issues/issue78_spec.rb +0 -72
- data/spec/issues/issue83_spec.rb +0 -30
- data/spec/issues/issue97_attachment.json +0 -1
- data/spec/issues/issue97_spec.rb +0 -175
- data/spec/lower_level_api/integration/basic_cancel_spec.rb +0 -83
- data/spec/lower_level_api/integration/basic_consume_spec.rb +0 -99
- data/spec/spec_helper.rb +0 -47
- data/spec/stress/channel_close_stress_spec.rb +0 -64
- data/spec/stress/channel_open_stress_spec.rb +0 -84
- data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +0 -28
- data/spec/stress/concurrent_consumers_stress_spec.rb +0 -71
- data/spec/stress/concurrent_publishers_stress_spec.rb +0 -54
- data/spec/stress/connection_open_close_spec.rb +0 -52
- data/spec/stress/merry_go_round_spec.rb +0 -105
- data/spec/tls/ca_certificate.pem +0 -29
- data/spec/tls/ca_key.pem +0 -52
- data/spec/tls/client_certificate.pem +0 -29
- data/spec/tls/client_key.pem +0 -51
- data/spec/tls/generate-server-cert.sh +0 -8
- data/spec/tls/server-openssl.cnf +0 -10
- data/spec/tls/server.csr +0 -16
- data/spec/tls/server_certificate.pem +0 -29
- data/spec/tls/server_key.pem +0 -51
- data/spec/toxiproxy_helper.rb +0 -28
- data/spec/unit/bunny_spec.rb +0 -15
- data/spec/unit/concurrent/atomic_fixnum_spec.rb +0 -35
- data/spec/unit/concurrent/condition_spec.rb +0 -82
- data/spec/unit/concurrent/linked_continuation_queue_spec.rb +0 -35
- data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +0 -73
- data/spec/unit/exchange_recovery_spec.rb +0 -39
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2edd88411f92dbdbb1d06b334006e446d5b3e3fb165f3baae3745bd066cf9651
|
4
|
+
data.tar.gz: 437032f606bb6f77fee02e65706e615f8a52c0e05467bbe257f1796fcedd624c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 698398dc76ca4e3dd11e3c5dc6b078998f23895bd3d975b01e1329c08c8ff0835cb9691d0108f0f6e13aaa769b870b258ff5e1de1958321be4804ca99b30a0be
|
7
|
+
data.tar.gz: 2a1fdcc61d683a991d07f601a986c5bc04d40cdd7155a1833dc7dba46be014c23d36612c505531b2f2adfe08ed057d6a493cbf5df368318205ffaf88659a88fb
|
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](
|
10
|
+
[Right here](https://www.rabbitmq.com/getstarted.html)!
|
11
11
|
|
12
12
|
|
13
13
|
## What is Bunny Good For?
|
@@ -43,12 +43,17 @@ Specific examples:
|
|
43
43
|
Web applications that display that information in the real time.
|
44
44
|
|
45
45
|
|
46
|
-
|
47
46
|
## Supported Ruby Versions
|
48
47
|
|
49
48
|
Modern Bunny versions support
|
50
49
|
|
51
|
-
* CRuby 2.
|
50
|
+
* CRuby 2.6 through 3.1 (inclusive)
|
51
|
+
* [TruffleRuby](https://www.graalvm.org/ruby/)
|
52
|
+
|
53
|
+
For environments that use TLS, Bunny expects Ruby installations to use a recent enough OpenSSL version that
|
54
|
+
**includes support for TLS 1.3**.
|
55
|
+
|
56
|
+
### JRuby
|
52
57
|
|
53
58
|
Bunny works sufficiently well on JRuby but there are known
|
54
59
|
JRuby bugs in versions prior to JRuby 9000 that cause high CPU burn. JRuby users should
|
@@ -59,8 +64,7 @@ Bunny `1.7.x` was the last version to support CRuby 1.9.3 and 1.8.7
|
|
59
64
|
|
60
65
|
## Supported RabbitMQ Versions
|
61
66
|
|
62
|
-
Bunny
|
63
|
-
Bunny `1.4.x` and earlier supports RabbitMQ 2.x and 3.x.
|
67
|
+
Modern Bunny releases target [currently supported RabbitMQ release series](https://www.rabbitmq.com/versions.html).
|
64
68
|
|
65
69
|
|
66
70
|
## Change Log
|
@@ -70,11 +74,8 @@ a stable public API.
|
|
70
74
|
|
71
75
|
Change logs per release series:
|
72
76
|
|
73
|
-
* [
|
74
|
-
* [2.
|
75
|
-
* [2.12.x](https://github.com/ruby-amqp/bunny/blob/2.12.x-stable/ChangeLog.md)
|
76
|
-
* [2.11.x](https://github.com/ruby-amqp/bunny/blob/2.11.x-stable/ChangeLog.md)
|
77
|
-
* [2.10.x](https://github.com/ruby-amqp/bunny/blob/2.10.x-stable/ChangeLog.md)
|
77
|
+
* [main](https://github.com/ruby-amqp/bunny/blob/main/ChangeLog.md) (most notable changes for all release series)
|
78
|
+
* [2.19.x](https://github.com/ruby-amqp/bunny/blob/2.19.x-stable/ChangeLog.md)
|
78
79
|
|
79
80
|
|
80
81
|
|
@@ -84,20 +85,20 @@ Change logs per release series:
|
|
84
85
|
|
85
86
|
[](http://badge.fury.io/rb/bunny)
|
86
87
|
|
87
|
-
###
|
88
|
+
### Bundler Dependency
|
88
89
|
|
89
|
-
To
|
90
|
+
To use Bunny in a project managed with Bundler:
|
90
91
|
|
91
|
-
```
|
92
|
-
gem
|
92
|
+
``` ruby
|
93
|
+
gem "bunny", ">= 2.19.0"
|
93
94
|
```
|
94
95
|
|
95
|
-
###
|
96
|
+
### With Rubygems
|
96
97
|
|
97
|
-
To
|
98
|
+
To install Bunny with RubyGems:
|
98
99
|
|
99
|
-
```
|
100
|
-
gem
|
100
|
+
```
|
101
|
+
gem install bunny
|
101
102
|
```
|
102
103
|
|
103
104
|
|
@@ -106,7 +107,7 @@ gem "bunny", ">= 2.13.0"
|
|
106
107
|
Below is a small snippet that demonstrates how to publish
|
107
108
|
and synchronously consume ("pull API") messages with Bunny.
|
108
109
|
|
109
|
-
For a 15 minute tutorial using more practical examples, see [Getting Started with RabbitMQ and Ruby using Bunny](
|
110
|
+
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).
|
110
111
|
|
111
112
|
``` ruby
|
112
113
|
require "bunny"
|
@@ -117,20 +118,31 @@ conn.start
|
|
117
118
|
|
118
119
|
# open a channel
|
119
120
|
ch = conn.create_channel
|
121
|
+
ch.confirm_select
|
120
122
|
|
121
123
|
# declare a queue
|
122
124
|
q = ch.queue("test1")
|
125
|
+
q.subscribe(manual_ack: true) do |delivery_info, metadata, payload|
|
126
|
+
puts "This is the message: #{payload}"
|
127
|
+
# acknowledge the delivery so that RabbitMQ can mark it for deletion
|
128
|
+
ch.ack(delivery_info.delivery_tag)
|
129
|
+
end
|
123
130
|
|
124
131
|
# publish a message to the default exchange which then gets routed to this queue
|
125
132
|
q.publish("Hello, everybody!")
|
126
133
|
|
127
|
-
#
|
128
|
-
|
134
|
+
# await confirmations from RabbitMQ, see
|
135
|
+
# https://www.rabbitmq.com/publishers.html#data-safety for details
|
136
|
+
ch.wait_for_confirms
|
129
137
|
|
130
|
-
|
138
|
+
# give the above consumer some time consume the delivery and print out the message
|
139
|
+
sleep 1
|
131
140
|
|
141
|
+
puts "Done"
|
142
|
+
|
143
|
+
ch.close
|
132
144
|
# close the connection
|
133
|
-
conn.
|
145
|
+
conn.close
|
134
146
|
```
|
135
147
|
|
136
148
|
|
@@ -142,17 +154,29 @@ For a 15 minute tutorial using more practical examples, see [Getting Started wit
|
|
142
154
|
|
143
155
|
### Guides
|
144
156
|
|
145
|
-
|
157
|
+
Bunny documentation guides are [under `docs/guides` in this repository](https://github.com/ruby-amqp/bunny/tree/main/docs/guides):
|
146
158
|
|
147
|
-
* [Queues and Consumers](
|
148
|
-
* [Exchanges and Publishers](
|
159
|
+
* [Queues and Consumers](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/queues.md)
|
160
|
+
* [Exchanges and Publishers](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/exchanges.md)
|
149
161
|
* [AMQP 0.9.1 Model Explained](http://www.rabbitmq.com/tutorials/amqp-concepts.html)
|
150
|
-
* [Connecting to RabbitMQ](
|
151
|
-
* [Error Handling and Recovery](
|
152
|
-
* [TLS/SSL Support](
|
153
|
-
* [Bindings](
|
154
|
-
* [Using RabbitMQ Extensions with Bunny](
|
155
|
-
* [Durability and Related Matters](
|
162
|
+
* [Connecting to RabbitMQ](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/connecting.md)
|
163
|
+
* [Error Handling and Recovery](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/error_handling.md)
|
164
|
+
* [TLS/SSL Support](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/tls.md)
|
165
|
+
* [Bindings](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/bindings.md)
|
166
|
+
* [Using RabbitMQ Extensions with Bunny](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/extensions.md)
|
167
|
+
* [Durability and Related Matters](https://github.com/ruby-amqp/bunny/tree/main/docs/guides/durability.md)
|
168
|
+
|
169
|
+
Some highly relevant RabbitMQ documentation guides:
|
170
|
+
|
171
|
+
* [Connections](https://www.rabbitmq.com/connections.html)
|
172
|
+
* [Channels](https://www.rabbitmq.com/channels.html)
|
173
|
+
* [Queues](https://www.rabbitmq.com/queues.html)
|
174
|
+
* [Quorum queues](https://www.rabbitmq.com/quorum-queues.html)
|
175
|
+
* [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))
|
176
|
+
* [Publishers](https://www.rabbitmq.com/publishers.html)
|
177
|
+
* [Consumers](https://www.rabbitmq.com/consumers.html)
|
178
|
+
* Data safety: publisher and consumer [Confirmations](https://www.rabbitmq.com/confirms.html)
|
179
|
+
* [Production Checklist](https://www.rabbitmq.com/production-checklist.html)
|
156
180
|
|
157
181
|
### API Reference
|
158
182
|
|
@@ -176,13 +200,6 @@ mailing list. Feel free to ask any questions that you may have.
|
|
176
200
|
[](https://travis-ci.org/ruby-amqp/bunny/)
|
177
201
|
|
178
202
|
|
179
|
-
### News & Announcements on Twitter
|
180
|
-
|
181
|
-
To subscribe for announcements of releases, important changes and so on, please follow [@rubyamqp](https://twitter.com/#!/rubyamqp) on Twitter.
|
182
|
-
|
183
|
-
More detailed announcements can be found in the [RabbitMQ Ruby clients blog](http://blog.rubyrabbitmq.info).
|
184
|
-
|
185
|
-
|
186
203
|
### Reporting Issues
|
187
204
|
|
188
205
|
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
|
@@ -374,7 +378,7 @@ module Bunny
|
|
374
378
|
# @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
|
375
379
|
# @api public
|
376
380
|
def default_exchange
|
377
|
-
Exchange.default(self)
|
381
|
+
@default_exchange ||= Exchange.default(self)
|
378
382
|
end
|
379
383
|
|
380
384
|
# Declares a headers exchange or looks it up in the cache of previously
|
@@ -392,7 +396,7 @@ module Bunny
|
|
392
396
|
# @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
|
393
397
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
|
394
398
|
def exchange(name, opts = {})
|
395
|
-
Exchange.new(self, opts.fetch(:type, :direct), name, opts)
|
399
|
+
find_exchange(name) || Exchange.new(self, opts.fetch(:type, :direct), name, opts)
|
396
400
|
end
|
397
401
|
|
398
402
|
# @endgroup
|
@@ -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 [
|
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
|
#
|
@@ -1156,7 +1227,7 @@ module Bunny
|
|
1156
1227
|
|
1157
1228
|
# @group Exchange operations (exchange.*)
|
1158
1229
|
|
1159
|
-
# Declares a exchange using
|
1230
|
+
# Declares a exchange using exchange.declare AMQP 0.9.1 method.
|
1160
1231
|
#
|
1161
1232
|
# @param [String] name The name of the exchange. Note that LF and CR characters
|
1162
1233
|
# will be stripped from the value.
|
@@ -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
|
-
@
|
1533
|
-
|
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}
|
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 + 1 : 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
|
data/lib/bunny/consumer.rb
CHANGED
@@ -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}
|
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}
|
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
|
@@ -70,7 +70,7 @@ module Bunny
|
|
70
70
|
return if !(wait_for_workers && @shutdown_timeout && was_running)
|
71
71
|
|
72
72
|
@shutdown_mutex.synchronize do
|
73
|
-
@shutdown_conditional.wait(@shutdown_mutex, @shutdown_timeout)
|
73
|
+
@shutdown_conditional.wait(@shutdown_mutex, @shutdown_timeout) if busy?
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
data/lib/bunny/cruby/socket.rb
CHANGED
@@ -32,6 +32,9 @@ module Bunny
|
|
32
32
|
socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
|
33
33
|
end
|
34
34
|
socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options.fetch(:keepalive, true)
|
35
|
+
socket.instance_eval do
|
36
|
+
@__bunny_socket_eof_flag__ = false
|
37
|
+
end
|
35
38
|
socket.extend self
|
36
39
|
socket.options = { :host => host, :port => port }.merge(options)
|
37
40
|
socket
|
data/lib/bunny/delivery_info.rb
CHANGED
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 [
|
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,17 @@ module Bunny
|
|
42
60
|
@exclusive = @options[:exclusive]
|
43
61
|
@server_named = @name.empty?
|
44
62
|
@auto_delete = @options[:auto_delete]
|
45
|
-
@
|
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)
|
71
|
+
# reassigns updated and verified arguments because Bunny::Channel#declare_queue
|
72
|
+
# accepts a map of options
|
73
|
+
@options[:arguments] = @arguments
|
46
74
|
|
47
75
|
@bindings = Array.new
|
48
76
|
|
@@ -158,9 +186,6 @@ module Bunny
|
|
158
186
|
# @option opts [Boolean] :ack (false) [DEPRECATED] Use :manual_ack instead
|
159
187
|
# @option opts [Boolean] :manual_ack (false) Will this consumer use manual acknowledgements?
|
160
188
|
# @option opts [Boolean] :exclusive (false) Should this consumer be exclusive for this queue?
|
161
|
-
# @option opts [Boolean] :block (false) Should the call block the calling thread? This option can be useful for keeping the main thread of
|
162
|
-
# a script alive. It is incompatible with automatic connection recovery
|
163
|
-
# and is not generally recommended.
|
164
189
|
# @option opts [#call] :on_cancellation Block to execute when this consumer is cancelled remotely (e.g. via the RabbitMQ Management plugin)
|
165
190
|
# @option opts [String] :consumer_tag Unique consumer identifier. It is usually recommended to let Bunny generate it for you.
|
166
191
|
# @option opts [Hash] :arguments ({}) Additional (optional) arguments, typically used by RabbitMQ extensions
|
@@ -392,5 +417,11 @@ module Bunny
|
|
392
417
|
h
|
393
418
|
end
|
394
419
|
end
|
420
|
+
|
421
|
+
def verify_type!(args)
|
422
|
+
q_type = (args || {})["x-queue-type"]
|
423
|
+
throw ArgumentError.new(
|
424
|
+
"unsupported queue type #{q_type.inspect}, supported ones: #{Types::KNOWN.join(', ')}") if (q_type and !Types.known?(q_type))
|
425
|
+
end
|
395
426
|
end
|
396
427
|
end
|
data/lib/bunny/reader_loop.rb
CHANGED
@@ -9,17 +9,17 @@ module Bunny
|
|
9
9
|
# @private
|
10
10
|
class ReaderLoop
|
11
11
|
|
12
|
-
def initialize(transport, session,
|
13
|
-
@transport
|
14
|
-
@session
|
15
|
-
@
|
16
|
-
@logger
|
12
|
+
def initialize(transport, session, session_error_handler)
|
13
|
+
@transport = transport
|
14
|
+
@session = session
|
15
|
+
@session_error_handler = session_error_handler
|
16
|
+
@logger = @session.logger
|
17
17
|
|
18
|
-
@mutex
|
18
|
+
@mutex = Mutex.new
|
19
19
|
|
20
|
-
@stopping
|
21
|
-
@stopped
|
22
|
-
@network_is_down
|
20
|
+
@stopping = false
|
21
|
+
@stopped = false
|
22
|
+
@network_is_down = false
|
23
23
|
end
|
24
24
|
|
25
25
|
|
@@ -37,7 +37,8 @@ module Bunny
|
|
37
37
|
begin
|
38
38
|
break if @mutex.synchronize { @stopping || @stopped || @network_is_down }
|
39
39
|
run_once
|
40
|
-
rescue AMQ::Protocol::EmptyResponseError, IOError, SystemCallError, Timeout::Error
|
40
|
+
rescue AMQ::Protocol::EmptyResponseError, IOError, SystemCallError, Timeout::Error,
|
41
|
+
OpenSSL::OpenSSLError => e
|
41
42
|
break if terminate? || @session.closing? || @session.closed?
|
42
43
|
|
43
44
|
@network_is_down = true
|
@@ -46,7 +47,7 @@ module Bunny
|
|
46
47
|
@session.handle_network_failure(e)
|
47
48
|
else
|
48
49
|
log_exception(e)
|
49
|
-
@
|
50
|
+
@session_error_handler.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
|
50
51
|
end
|
51
52
|
rescue ShutdownSignal => _
|
52
53
|
@mutex.synchronize { @stopping = true }
|
@@ -57,7 +58,7 @@ module Bunny
|
|
57
58
|
log_exception(e)
|
58
59
|
|
59
60
|
@network_is_down = true
|
60
|
-
@
|
61
|
+
@session_error_handler.raise(Bunny::NetworkFailure.new("caught an unexpected exception in the network loop: #{e.message}", e))
|
61
62
|
end
|
62
63
|
rescue Errno::EBADF => _ebadf
|
63
64
|
break if terminate?
|
@@ -115,7 +116,14 @@ module Bunny
|
|
115
116
|
end
|
116
117
|
|
117
118
|
def join
|
118
|
-
|
119
|
+
# Thread#join can/would trigger a re-raise of an unhandled exception in this thread.
|
120
|
+
# In addition, Thread.handle_interrupt can be used by other libraries or application code
|
121
|
+
# that would make this join operation fail with an obscure exception.
|
122
|
+
# So we try to save everyone some really unpleasant debugging time by introducing
|
123
|
+
# this condition which typically would not evaluate to true anyway.
|
124
|
+
#
|
125
|
+
# See ruby-amqp/bunny#589 and ruby-amqp/bunny#590 for background.
|
126
|
+
@thread.join if @thread && @thread != Thread.current
|
119
127
|
end
|
120
128
|
|
121
129
|
def kill
|