bunny 2.14.2 → 2.16.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a6ffb6e1661c9921afd766382444c1d194f5b816d35021f9f49ab4382adced6
4
- data.tar.gz: 4f7ef1377379a4fa087110316c149c0f012239247537467bfd788463d8c0a904
3
+ metadata.gz: 94a05191f06bd28c3c4714a67c70a5097341f7d07961cb97df83ad5414a0e541
4
+ data.tar.gz: 3521b4979e62eb7a5d6c1f54cb5a17cbda33706f696288ec2c8a0ee0397c3ddf
5
5
  SHA512:
6
- metadata.gz: 73ada01a49fb86a5ffe95548b79df15169cd63ba47481c2303f5ea314f04e14e97c4f9e7e42b095969bf5259633d15803a4eb116743c054007d4694af62b6fa2
7
- data.tar.gz: b6c533137ea821b45c2dd7e8cc54a87c09384a6e15bad8ae505c3c9ea2ef3c3ed8a53153832bc1a0773adc566888a832e689837abfe8f5f4d1a90e7cf2966da6
6
+ metadata.gz: 54314055b9f79e3c334d461f0a63f17fa50e7fe0b39fa71a9314b194db02a8416a057e66123f8b2d7d13353b69f018799a785dd59ea54eeea3d882ec8511b650
7
+ data.tar.gz: 9721730e57e5da633568b859f8df0feada37d4303b94f68e78d6a291d0d9d2e6409fa5a7fdcbb59ea5cb5a557c04e750ec7a1098496ab439bd2077b260ea4c3c
@@ -1,3 +1,4 @@
1
+ dist: bionic
1
2
  language: ruby
2
3
  bundler_args: --without development
3
4
  cache: bundler
@@ -10,10 +11,11 @@ before_script:
10
11
  script: "bundle exec rake integration_without_recovery"
11
12
  rvm:
12
13
  - ruby-head
13
- - "2.6.0"
14
- - "2.5.1"
15
- - "2.4.2"
16
- - "2.3.5"
14
+ - "2.7.1"
15
+ - "2.6.6"
16
+ - "2.5.8"
17
+ - "2.4.10"
18
+ - "2.3.8"
17
19
  notifications:
18
20
  email: michael@rabbitmq.com
19
21
  services:
@@ -21,8 +23,8 @@ services:
21
23
  branches:
22
24
  only:
23
25
  - master
24
- - 2.12.x-stable
25
- - 2.11.x-stable
26
+ - 2.14.x-stable
27
+ - 2.13.x-stable
26
28
  env:
27
29
  - CI=true
28
30
  matrix:
@@ -1,22 +1,43 @@
1
- ## Changes between Bunny 2.14.2 and 2.14.3 (in development)
1
+ ## Changes between Bunny 2.16.0 and 2.17.0 (undefined)
2
2
 
3
3
  No changes yet.
4
4
 
5
5
 
6
- ## Changes between Bunny 2.14.1 and 2.14.2 (Apr 24th, 2019)
6
+ ## Changes between Bunny 2.15.0 and 2.16.0 (Aug 14th, 2020)
7
7
 
8
- ### Lazy Peer Certificate Chain Information Logging
8
+ ### Asynchronous Exception Delegate
9
9
 
10
- Peer certificate chain information is now logged lazily, which prevents
11
- an obscure exception originating ASN.1 parser and makes the logging
12
- code evaluate only when it is really necessary.
10
+ Bunny now can delete asynchronous connection (`Bunny::Session`) exception to an arbitrary
11
+ delegate object. Use the `:session_error_handler` connection setting to pass it.
12
+ The value defaults to `Thread.current`.
13
13
 
14
- GitHub issue: [#578](https://github.com/ruby-amqp/bunny/pull/578)
14
+ Contributed by @bbascarevic.
15
15
 
16
- Contributed by Garrett Thornburg.
16
+ GitHub issue: [ruby-amqp/bunny#597](https://github.com/ruby-amqp/bunny/issues/597)
17
+
18
+
19
+ ## Changes between Bunny 2.14.0 and 2.15.0 (Apr 8th, 2020)
20
+
21
+ ### More Defensive Thread Join Operations
22
+
23
+ Bunny is now more defensive around thread join operations which it performs
24
+ when stopping its consumer work pool.
25
+
26
+ `Thread#join` can cause an unhandled exception to be re-raised at
27
+ a very surprising moment. This behavior can also be affected by 3rd party
28
+ libraries, e.g. those that do connection pooling. While Bunny cannot
29
+ fully avoid every possible surprising failure, it now avoids at least
30
+ one such problematic interaction triggered by a custom [interrupt handler](https://ruby-doc.org/core-2.5.1/Thread.html#method-c-handle_interrupt)
31
+ in a 3rd party library.
32
+
33
+ GitHub issue: [#589](https://github.com/ruby-amqp/bunny/issues/589)
17
34
 
35
+ Contributed by @fuegas.
18
36
 
19
- ## Changes between Bunny 2.14.0 and 2.14.1 (Feb 26th, 2019)
37
+ ### Dependency Updates
38
+
39
+ `amq-protocol` dependency has been bumped to `2.3.1` to support `connection.update-secret`
40
+ protocol extension.
20
41
 
21
42
  ### Gem Installation Fixed on Windows
22
43
 
@@ -24,7 +45,16 @@ Contributed by Garrett Thornburg.
24
45
 
25
46
  Contributed by Jack Xiaosong Xu.
26
47
 
27
- GitHub issue: [#573](https://github.com/ruby-amqp/bunny/pull/574)
48
+ ### Lazy Peer Certificate Chain Information Logging
49
+
50
+ Peer certificate chain information is now logged lazily, which prevents
51
+ an obscure exception originating ASN.1 parser and makes the logging
52
+ code evaluate only when it is really necessary.
53
+
54
+ GitHub issue: [#578](https://github.com/ruby-amqp/bunny/pull/578)
55
+
56
+ Contributed by Garrett Thornburg.
57
+
28
58
 
29
59
  ## Changes between Bunny 2.13.0 and 2.14.0 (Feb 20th, 2019)
30
60
 
data/Gemfile CHANGED
@@ -33,8 +33,8 @@ group :development do
33
33
  end
34
34
 
35
35
  group :test do
36
- gem "rspec", "~> 3.8.0"
37
- gem "rabbitmq_http_api_client", "~> 1.11.0", require: "rabbitmq/http/client"
36
+ gem "rspec", "~> 3.9.0"
37
+ gem "rabbitmq_http_api_client", "~> 1.13.0", require: "rabbitmq/http/client"
38
38
  gem "toxiproxy", "~> 1.0.3"
39
39
  end
40
40
 
data/README.md CHANGED
@@ -48,7 +48,7 @@ Specific examples:
48
48
 
49
49
  Modern Bunny versions support
50
50
 
51
- * CRuby 2.2 through 2.5 (inclusive)
51
+ * CRuby 2.3 through 2.6 (inclusive)
52
52
 
53
53
  Bunny works sufficiently well on JRuby but there are known
54
54
  JRuby bugs in versions prior to JRuby 9000 that cause high CPU burn. JRuby users should
@@ -71,10 +71,10 @@ a stable public API.
71
71
  Change logs per release series:
72
72
 
73
73
  * [master](https://github.com/ruby-amqp/bunny/blob/master/ChangeLog.md)
74
+ * [2.14.x](https://github.com/ruby-amqp/bunny/blob/2.13.x-stable/ChangeLog.md)
74
75
  * [2.13.x](https://github.com/ruby-amqp/bunny/blob/2.13.x-stable/ChangeLog.md)
75
76
  * [2.12.x](https://github.com/ruby-amqp/bunny/blob/2.12.x-stable/ChangeLog.md)
76
77
  * [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)
78
78
 
79
79
 
80
80
 
@@ -97,7 +97,7 @@ gem install bunny
97
97
  To use Bunny in a project managed with Bundler:
98
98
 
99
99
  ``` ruby
100
- gem "bunny", ">= 2.13.0"
100
+ gem "bunny", ">= 2.14.1"
101
101
  ```
102
102
 
103
103
 
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.name = "bunny"
9
9
  s.version = Bunny::VERSION.dup
10
10
  s.homepage = "http://rubybunny.info"
11
- s.summary = "Easy to use Ruby client for RabbitMQ"
12
- s.description = "Easy to use, feature complete Ruby client for RabbitMQ"
11
+ s.summary = "Popular easy to use Ruby client for RabbitMQ"
12
+ s.description = "Easy to use, feature complete Ruby client for RabbitMQ 3.3 and later versions."
13
13
  s.license = "MIT"
14
14
  s.required_ruby_version = Gem::Requirement.new(">= 2.2")
15
15
 
@@ -21,10 +21,10 @@ Gem::Specification.new do |s|
21
21
  "Michael S. Klishin",
22
22
  "Stefan Kaes"]
23
23
 
24
- s.email = ["mklishin@pivotal.io"]
24
+ s.email = ["michael.s.klishin@gmail.com"]
25
25
 
26
26
  # Dependencies
27
- s.add_runtime_dependency 'amq-protocol', '~> 2.3', '>= 2.3.0'
27
+ s.add_runtime_dependency 'amq-protocol', '~> 2.3', '>= 2.3.1'
28
28
 
29
29
  # Files.
30
30
  s.extra_rdoc_files = ["README.md"]
@@ -7,11 +7,15 @@ RUN wget -O - "https://github.com/rabbitmq/signing-keys/releases/download/2.0/ra
7
7
  COPY apt/sources.list.d/bintray.rabbitmq.list /etc/apt/sources.list.d/bintray.rabbitmq.list
8
8
  COPY apt/preferences.d/erlang /etc/apt/preferences.d/erlang
9
9
 
10
- RUN apt-get update -y
10
+ RUN apt-get update -y && apt-get upgrade -y
11
+
12
+ RUN apt-get install -y erlang-base \
13
+ erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets \
14
+ erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key \
15
+ erlang-runtime-tools erlang-snmp erlang-ssl \
16
+ erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl
11
17
 
12
- RUN apt-get upgrade -y && \
13
- apt-get install -y erlang-asn1 erlang-crypto erlang-public-key erlang-ssl && \
14
- apt-get install -y rabbitmq-server
18
+ RUN apt-get install -y rabbitmq-server
15
19
 
16
20
  COPY docker-entrypoint.sh /
17
21
 
@@ -6,9 +6,9 @@ delay=5
6
6
  echo 'Starting a RabbitMQ node'
7
7
  $server -detached
8
8
 
9
- echo "Waiting $delay seconds for RabbitMQ to start."
9
+ echo "Waiting for RabbitMQ to finish startup..."
10
10
 
11
- sleep $delay
11
+ $ctl await_startup --timeout 15
12
12
 
13
13
  $ctl add_user bunny_gem bunny_password
14
14
  $ctl add_user bunny_reader reader_password
@@ -1156,7 +1156,7 @@ module Bunny
1156
1156
 
1157
1157
  # @group Exchange operations (exchange.*)
1158
1158
 
1159
- # Declares a exchange using echange.declare AMQP 0.9.1 method.
1159
+ # Declares a exchange using exchange.declare AMQP 0.9.1 method.
1160
1160
  #
1161
1161
  # @param [String] name The name of the exchange. Note that LF and CR characters
1162
1162
  # will be stripped from the value.
@@ -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
@@ -158,9 +158,6 @@ module Bunny
158
158
  # @option opts [Boolean] :ack (false) [DEPRECATED] Use :manual_ack instead
159
159
  # @option opts [Boolean] :manual_ack (false) Will this consumer use manual acknowledgements?
160
160
  # @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
161
  # @option opts [#call] :on_cancellation Block to execute when this consumer is cancelled remotely (e.g. via the RabbitMQ Management plugin)
165
162
  # @option opts [String] :consumer_tag Unique consumer identifier. It is usually recommended to let Bunny generate it for you.
166
163
  # @option opts [Hash] :arguments ({}) Additional (optional) arguments, typically used by RabbitMQ extensions
@@ -9,17 +9,17 @@ module Bunny
9
9
  # @private
10
10
  class ReaderLoop
11
11
 
12
- def initialize(transport, session, session_thread)
13
- @transport = transport
14
- @session = session
15
- @session_thread = session_thread
16
- @logger = @session.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 = Mutex.new
18
+ @mutex = Mutex.new
19
19
 
20
- @stopping = false
21
- @stopped = false
22
- @network_is_down = false
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 => e
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
- @session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
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
- @session_thread.raise(Bunny::NetworkFailure.new("caught an unexpected exception in the network loop: #{e.message}", e))
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
- @thread.join if @thread
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
@@ -124,6 +124,7 @@ module Bunny
124
124
  # @option connection_string_or_opts [Integer] :recovery_attempts (nil) Max number of recovery attempts, nil means forever
125
125
  # @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.
126
126
  # @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)?
127
+ # @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.
127
128
  #
128
129
  # @option optz [String] :auth_mechanism ("PLAIN") Authentication mechanism, PLAIN or EXTERNAL
129
130
  # @option optz [String] :locale ("PLAIN") Locale RabbitMQ should use
@@ -171,6 +172,7 @@ module Bunny
171
172
  else
172
173
  opts[:automatically_recover] || opts[:automatic_recovery]
173
174
  end
175
+ @recovering_from_network_failure = false
174
176
  @max_recovery_attempts = opts[:recovery_attempts]
175
177
  @recovery_attempts = @max_recovery_attempts
176
178
  # When this is set, connection attempts won't be reset after
@@ -184,6 +186,7 @@ module Bunny
184
186
  @continuation_timeout = opts.fetch(:continuation_timeout, DEFAULT_CONTINUATION_TIMEOUT)
185
187
 
186
188
  @status = :not_connected
189
+ @manually_closed = false
187
190
  @blocked = false
188
191
 
189
192
  # these are negotiated with the broker during the connection tuning phase
@@ -211,9 +214,9 @@ module Bunny
211
214
  @address_index_mutex = @mutex_impl.new
212
215
 
213
216
  @channels = Hash.new
214
- @recovery_completed = opts[:recovery_completed]
217
+ @recovery_completed = opts[:recovery_completed]
215
218
 
216
- @origin_thread = Thread.current
219
+ @session_error_handler = opts.fetch(:session_error_handler, Thread.current)
217
220
 
218
221
  self.reset_continuations
219
222
  self.initialize_transport
@@ -340,6 +343,14 @@ module Bunny
340
343
  self
341
344
  end
342
345
 
346
+ def update_secret(value, reason)
347
+ @transport.send_frame(AMQ::Protocol::Connection::UpdateSecret.encode(value, reason))
348
+ @last_update_secret_ok = wait_on_continuations
349
+ raise_if_continuation_resulted_in_a_connection_error!
350
+
351
+ @last_update_secret_ok
352
+ end
353
+
343
354
  # Socket operation write timeout used by this connection
344
355
  # @return [Integer]
345
356
  # @private
@@ -630,6 +641,8 @@ module Bunny
630
641
  when AMQ::Protocol::Connection::Unblocked then
631
642
  @blocked = false
632
643
  @unblock_callback.call(method) if @unblock_callback
644
+ when AMQ::Protocol::Connection::UpdateSecretOk then
645
+ @continuations.push(method)
633
646
  when AMQ::Protocol::Channel::Close then
634
647
  begin
635
648
  ch = synchronised_find_channel(ch_number)
@@ -850,7 +863,7 @@ module Bunny
850
863
 
851
864
  clean_up_on_shutdown
852
865
  if threaded?
853
- @origin_thread.raise(@last_connection_error)
866
+ @session_error_handler.raise(@last_connection_error)
854
867
  else
855
868
  raise @last_connection_error
856
869
  end
@@ -1007,7 +1020,7 @@ module Bunny
1007
1020
 
1008
1021
  # @private
1009
1022
  def reader_loop
1010
- @reader_loop ||= ReaderLoop.new(@transport, self, Thread.current)
1023
+ @reader_loop ||= ReaderLoop.new(@transport, self, @session_error_handler)
1011
1024
  end
1012
1025
 
1013
1026
  # @private
@@ -1270,7 +1283,7 @@ module Bunny
1270
1283
  end
1271
1284
 
1272
1285
  if threaded?
1273
- @origin_thread.raise(e)
1286
+ @session_error_handler.raise(e)
1274
1287
  else
1275
1288
  raise e
1276
1289
  end
@@ -1316,7 +1329,7 @@ module Bunny
1316
1329
  @transport = Transport.new(self,
1317
1330
  host_from_address(address),
1318
1331
  port_from_address(address),
1319
- @opts.merge(:session_thread => @origin_thread)
1332
+ @opts.merge(:session_error_handler => @session_error_handler)
1320
1333
  )
1321
1334
 
1322
1335
  # Reset the cached progname for the logger only when no logger was provided
@@ -35,7 +35,7 @@ module Bunny
35
35
 
36
36
  def initialize(session, host, port, opts)
37
37
  @session = session
38
- @session_thread = opts[:session_thread]
38
+ @session_error_handler = opts[:session_error_handler]
39
39
  @host = host
40
40
  @port = port
41
41
  @opts = opts
@@ -146,7 +146,7 @@ module Bunny
146
146
  if @session.automatically_recover?
147
147
  @session.handle_network_failure(e)
148
148
  else
149
- @session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
149
+ @session_error_handler.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
150
150
  end
151
151
  end
152
152
  end
@@ -170,7 +170,7 @@ module Bunny
170
170
  if @session.automatically_recover?
171
171
  @session.handle_network_failure(e)
172
172
  else
173
- @session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
173
+ @session_error_handler.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
174
174
  end
175
175
  end
176
176
  end
@@ -188,7 +188,7 @@ module Bunny
188
188
  if @session.automatically_recover?
189
189
  @session.handle_network_failure(e)
190
190
  else
191
- @session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
191
+ @session_error_handler.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
192
192
  end
193
193
  end
194
194
  end
@@ -245,7 +245,7 @@ module Bunny
245
245
  if @session.automatically_recover?
246
246
  raise
247
247
  else
248
- @session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
248
+ @session_error_handler.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
249
249
  end
250
250
  end
251
251
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Bunny
4
4
  # @return [String] Version of the library
5
- VERSION = "2.14.2"
5
+ VERSION = "2.16.1"
6
6
  end
data/repl CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/bin/sh
2
2
 
3
- bundle exec ripl -Ilib -r'bunny' -r'ripl/multi_line' -r'ripl/irb'
3
+ bundle exec ruby `which ripl` -Ilib -r'bunny' -r'ripl/multi_line' -r'ripl/irb'
@@ -20,7 +20,7 @@ describe Bunny::Consumer, "#cancel" do
20
20
  t = Thread.new do
21
21
  ch = connection.create_channel
22
22
  q = ch.queue(queue_name, auto_delete: true, durable: false)
23
- consumer = q.subscribe(block: false) do |_, _, payload|
23
+ consumer = q.subscribe do |_, _, payload|
24
24
  delivered_data << payload
25
25
  end
26
26
 
@@ -58,7 +58,7 @@ describe Bunny::Consumer, "#cancel" do
58
58
  delivered_data << payload
59
59
  end
60
60
 
61
- q.subscribe_with(consumer, block: false)
61
+ q.subscribe_with(consumer)
62
62
  end
63
63
  t.abort_on_exception = true
64
64
  sleep 1.0
@@ -91,7 +91,7 @@ describe Bunny::Consumer, "#cancel" do
91
91
  delivered_data << payload
92
92
  end
93
93
 
94
- q.subscribe_with(consumer, block: false)
94
+ q.subscribe_with(consumer)
95
95
  end
96
96
  t.abort_on_exception = true
97
97
  sleep 1.0
@@ -122,7 +122,7 @@ describe Bunny::Consumer, "#cancel" do
122
122
  delivered_data << payload
123
123
  end
124
124
 
125
- q.subscribe_with(consumer, block: false)
125
+ q.subscribe_with(consumer)
126
126
  end
127
127
  t.abort_on_exception = true
128
128
  sleep 1.0
@@ -189,17 +189,17 @@ describe Bunny::Queue, "#subscribe" do
189
189
  ch = connection.create_channel
190
190
  q = ch.queue(queue_name)
191
191
 
192
- c1 = q.subscribe(exclusive: false, manual_ack: false, block: false) do |delivery_info, properties, payload|
192
+ c1 = q.subscribe(exclusive: false, manual_ack: false) do |delivery_info, properties, payload|
193
193
  end
194
194
  c1.cancel
195
195
 
196
- c2 = q.subscribe(exclusive: false, manual_ack: false, block: false) do |delivery_info, properties, payload|
196
+ c2 = q.subscribe(exclusive: false, manual_ack: false) do |delivery_info, properties, payload|
197
197
  delivered_keys << delivery_info.routing_key
198
198
  delivered_data << payload
199
199
  end
200
200
  c2.cancel
201
201
 
202
- q.subscribe(exclusive: false, manual_ack: false, block: true) do |delivery_info, properties, payload|
202
+ q.subscribe(exclusive: false, manual_ack: false) do |delivery_info, properties, payload|
203
203
  delivered_keys << delivery_info.routing_key
204
204
  delivered_data << payload
205
205
  end
@@ -3,248 +3,260 @@ require "spec_helper"
3
3
 
4
4
  require "socket"
5
5
 
6
- unless ENV["CI"]
7
- CERTIFICATE_DIR = ENV.fetch("BUNNY_CERTIFICATE_DIR", "./spec/tls")
8
- puts "Will use certificates from #{CERTIFICATE_DIR}"
9
-
10
- shared_examples_for "successful TLS connection" do
11
- it "succeeds" do
12
- expect(subject).to be_tls
13
- ch = subject.create_channel
14
- ch.confirm_select
15
-
16
- q = ch.queue("", exclusive: true)
17
- x = ch.default_exchange
18
-
19
- x.publish("xyzzy", routing_key: q.name).
20
- publish("xyzzy", routing_key: q.name).
21
- publish("xyzzy", routing_key: q.name).
22
- publish("xyzzy", routing_key: q.name)
23
-
24
- x.wait_for_confirms
25
- expect(q.message_count).to eq 4
26
-
27
- i = 0
28
- q.subscribe do |delivery_info, _, payload|
29
- i += 1
30
- end
31
- sleep 1.0
32
- expect(i).to eq 4
33
- expect(q.message_count).to eq 0
34
-
35
- ch.close
36
- end
37
- end
6
+ CERTIFICATE_DIR = ENV.fetch("BUNNY_CERTIFICATE_DIR", "./spec/tls")
7
+ puts "Will use certificates from #{CERTIFICATE_DIR}"
38
8
 
39
- def local_hostname
40
- ENV.fetch("BUNNY_RABBITMQ_HOSTNAME", "localhost")
41
- end
9
+ shared_examples_for "successful TLS connection" do
10
+ it "succeeds", skip: ENV["CI"] do
11
+ expect(subject).to be_tls
12
+ ch = subject.create_channel
13
+ ch.confirm_select
14
+
15
+ q = ch.queue("", exclusive: true)
16
+ x = ch.default_exchange
17
+
18
+ x.publish("xyzzy", routing_key: q.name).
19
+ publish("xyzzy", routing_key: q.name).
20
+ publish("xyzzy", routing_key: q.name).
21
+ publish("xyzzy", routing_key: q.name)
42
22
 
43
- context "initialized with :tls => true" do
44
- let(:subject) do
45
- Bunny.new(
46
- hostname: local_hostname(),
47
- user: "bunny_gem",
48
- password: "bunny_password",
49
- vhost: "bunny_testbed",
50
- tls: true,
51
- verify_peer: verify_peer,
52
- tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
53
- tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
54
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"])
23
+ x.wait_for_confirms
24
+ expect(q.message_count).to eq 4
25
+
26
+ i = 0
27
+ q.subscribe do |delivery_info, _, payload|
28
+ i += 1
55
29
  end
30
+ sleep 1.0
31
+ expect(i).to eq 4
32
+ expect(q.message_count).to eq 0
56
33
 
57
- context "peer verification is off" do
58
- let(:verify_peer) { false }
34
+ ch.close
35
+ end
36
+ end
59
37
 
60
- it "uses TLS port" do
61
- expect(subject.port).to eq AMQ::Protocol::TLS_PORT
62
- end
38
+ def local_hostname
39
+ ENV.fetch("BUNNY_RABBITMQ_HOSTNAME", "localhost")
40
+ end
63
41
 
64
- it "sends the SNI details" do
65
- # https://github.com/ruby-amqp/bunny/issues/440
66
- subject.start
67
- expect(subject.transport.socket.hostname).to_not be_empty
68
- end
42
+ def no_tls12_supported?
43
+ not tls12_supported?
44
+ end
69
45
 
70
- after :each do
71
- subject.close
72
- end
73
- end
46
+ def tls12_supported?
47
+ begin
48
+ ctx = OpenSSL::SSL::SSLContext.new
49
+ ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
50
+ true
51
+ rescue
52
+ false
53
+ end
54
+ end
74
55
 
75
- context "peer verification is on" do
76
- let(:verify_peer) { true }
56
+ context "initialized with tls: true", skip: ENV["CI"] do
57
+ let(:subject) do
58
+ Bunny.new(
59
+ hostname: local_hostname(),
60
+ user: "bunny_gem",
61
+ password: "bunny_password",
62
+ vhost: "bunny_testbed",
63
+ tls: true,
64
+ verify_peer: verify_peer,
65
+ tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
66
+ tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
67
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"])
68
+ end
69
+
70
+ context "peer verification is off" do
71
+ let(:verify_peer) { false }
77
72
 
78
- it "uses TLS port" do
79
- expect(subject.port).to eq AMQ::Protocol::TLS_PORT
80
- end
73
+ it "uses TLS port" do
74
+ expect(subject.port).to eq AMQ::Protocol::TLS_PORT
81
75
  end
82
- end
83
76
 
84
- describe "TLS connection to RabbitMQ with client certificates" do
85
- let(:subject) do
86
- c = Bunny.new(
87
- hostname: local_hostname(),
88
- username: "bunny_gem",
89
- password: "bunny_password",
90
- vhost: "bunny_testbed",
91
- tls: true,
92
- tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
93
- tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
94
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
95
- verify_peer: false)
96
- c.start
97
- c
77
+ it "sends the SNI details" do
78
+ # https://github.com/ruby-amqp/bunny/issues/440
79
+ subject.start
80
+ expect(subject.transport.socket.hostname).to_not be_empty
98
81
  end
99
82
 
100
83
  after :each do
101
84
  subject.close
102
85
  end
103
-
104
- include_examples "successful TLS connection"
105
86
  end
106
87
 
88
+ context "peer verification is on" do
89
+ let(:verify_peer) { true }
107
90
 
108
- describe "TLS connection to RabbitMQ without client certificates" do
109
- let(:subject) do
110
- c = Bunny.new(
111
- hostname: local_hostname(),
112
- username: "bunny_gem",
113
- password: "bunny_password",
114
- vhost: "bunny_testbed",
115
- tls: true,
116
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
117
- verify_peer: false)
118
- c.start
119
- c
91
+ it "uses TLS port" do
92
+ expect(subject.port).to eq AMQ::Protocol::TLS_PORT
120
93
  end
94
+ end
95
+ end
121
96
 
122
- after :each do
123
- subject.close
124
- end
97
+ describe "TLS connection to RabbitMQ with client certificates", skip: ENV["CI"] do
98
+ let(:subject) do
99
+ c = Bunny.new(
100
+ hostname: local_hostname(),
101
+ username: "bunny_gem",
102
+ password: "bunny_password",
103
+ vhost: "bunny_testbed",
104
+ tls: true,
105
+ tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
106
+ tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
107
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
108
+ verify_peer: false)
109
+ c.start
110
+ c
111
+ end
125
112
 
126
- include_examples "successful TLS connection"
113
+ after :each do
114
+ subject.close
127
115
  end
128
116
 
117
+ include_examples "successful TLS connection"
118
+ end
129
119
 
130
- describe "TLS connection to RabbitMQ with a connection string" do
131
- let(:subject) do
132
- c = Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed",
133
- tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
134
- tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
135
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
136
- verify_peer: false)
137
- c.start
138
- c
139
- end
140
120
 
141
- after :each do
142
- subject.close
143
- end
121
+ describe "TLS connection to RabbitMQ without client certificates", skip: ENV["CI"] do
122
+ let(:subject) do
123
+ c = Bunny.new(
124
+ hostname: local_hostname(),
125
+ username: "bunny_gem",
126
+ password: "bunny_password",
127
+ vhost: "bunny_testbed",
128
+ tls: true,
129
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
130
+ verify_peer: false)
131
+ c.start
132
+ c
133
+ end
144
134
 
145
- include_examples "successful TLS connection"
135
+ after :each do
136
+ subject.close
137
+ end
146
138
 
147
- context "when URI contains query parameters" do
148
- subject(:session) do
149
- Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed?heartbeat=10&connection_timeout=100&channel_max=1000&verify=false&cacertfile=#{CERTIFICATE_DIR}/ca_certificate.pem&certfile=#{CERTIFICATE_DIR}/client_certificate.pem&keyfile=#{CERTIFICATE_DIR}/client_key.pem")
150
- end
139
+ include_examples "successful TLS connection"
140
+ end
151
141
 
152
- it "parses extra connection parameters" do
153
- session.start
154
142
 
155
- expect(session.uses_tls?).to eq(true)
156
- expect(session.transport.verify_peer).to eq(false)
157
- expect(session.transport.tls_ca_certificates).to eq(["#{CERTIFICATE_DIR}/ca_certificate.pem"])
158
- expect(session.transport.tls_certificate_path).to eq("#{CERTIFICATE_DIR}/client_certificate.pem")
159
- expect(session.transport.tls_key_path).to eq("#{CERTIFICATE_DIR}/client_key.pem")
160
- end
161
- end
143
+ describe "TLS connection to RabbitMQ with a connection string", skip: ENV["CI"] do
144
+ let(:subject) do
145
+ c = Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed",
146
+ tls_cert: "#{CERTIFICATE_DIR}/client_certificate.pem",
147
+ tls_key: "#{CERTIFICATE_DIR}/client_key.pem",
148
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
149
+ verify_peer: false)
150
+ c.start
151
+ c
162
152
  end
163
153
 
154
+ after :each do
155
+ subject.close
156
+ end
164
157
 
165
- describe "TLS connection to RabbitMQ with a connection string and w/o client certificate and key" do
166
- let(:subject) do
167
- c = Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed",
168
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
169
- verify_peer: verify_peer)
170
- c.start
171
- c
158
+ include_examples "successful TLS connection"
159
+
160
+ context "when URI contains query parameters" do
161
+ subject(:session) do
162
+ Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed?heartbeat=10&connection_timeout=100&channel_max=1000&verify=false&cacertfile=#{CERTIFICATE_DIR}/ca_certificate.pem&certfile=#{CERTIFICATE_DIR}/client_certificate.pem&keyfile=#{CERTIFICATE_DIR}/client_key.pem")
172
163
  end
173
164
 
174
- after :each do
175
- subject.close
165
+ it "parses extra connection parameters" do
166
+ session.start
167
+
168
+ expect(session.uses_tls?).to eq(true)
169
+ expect(session.transport.verify_peer).to eq(false)
170
+ expect(session.transport.tls_ca_certificates).to eq(["#{CERTIFICATE_DIR}/ca_certificate.pem"])
171
+ expect(session.transport.tls_certificate_path).to eq("#{CERTIFICATE_DIR}/client_certificate.pem")
172
+ expect(session.transport.tls_key_path).to eq("#{CERTIFICATE_DIR}/client_key.pem")
176
173
  end
174
+ end
175
+ end
177
176
 
178
- context "peer verification is off" do
179
- let(:verify_peer) { false }
180
177
 
181
- include_examples "successful TLS connection"
178
+ describe "TLS connection to RabbitMQ with a connection string and w/o client certificate and key", skip: ENV["CI"] do
179
+ let(:subject) do
180
+ c = Bunny.new("amqps://bunny_gem:bunny_password@#{local_hostname()}/bunny_testbed",
181
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
182
+ verify_peer: verify_peer)
183
+ c.start
184
+ c
185
+ end
182
186
 
183
- it "sends the SNI details" do
184
- # https://github.com/ruby-amqp/bunny/issues/440
185
- expect(subject.transport.socket.hostname).to_not be_empty
186
- end
187
- end
187
+ after :each do
188
+ subject.close
189
+ end
188
190
 
189
- context "peer verification is on" do
190
- let(:verify_peer) { true }
191
+ context "peer verification is off" do
192
+ let(:verify_peer) { false }
191
193
 
192
- include_examples "successful TLS connection"
194
+ include_examples "successful TLS connection"
193
195
 
194
- it "sends the SNI details" do
195
- # https://github.com/ruby-amqp/bunny/issues/440
196
- expect(subject.transport.socket.hostname).to_not be_empty
197
- end
196
+ it "sends the SNI details" do
197
+ # https://github.com/ruby-amqp/bunny/issues/440
198
+ expect(subject.transport.socket.hostname).to_not be_empty
198
199
  end
199
200
  end
200
201
 
202
+ context "peer verification is on" do
203
+ let(:verify_peer) { true }
201
204
 
202
- describe "TLS connection to RabbitMQ with client certificates provided inline" do
203
- let(:subject) do
204
- c = Bunny.new(
205
- hostname: local_hostname(),
206
- username: "bunny_gem",
207
- password: "bunny_password",
208
- vhost: "bunny_testbed",
209
- tls: true,
210
- tls_cert: File.read("#{CERTIFICATE_DIR}/client_certificate.pem"),
211
- tls_key: File.read("#{CERTIFICATE_DIR}/client_key.pem"),
212
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
213
- verify_peer: false)
214
- c.start
215
- c
216
- end
205
+ include_examples "successful TLS connection"
217
206
 
218
- after :each do
219
- subject.close
207
+ it "sends the SNI details" do
208
+ # https://github.com/ruby-amqp/bunny/issues/440
209
+ expect(subject.transport.socket.hostname).to_not be_empty
220
210
  end
211
+ end
212
+ end
221
213
 
222
- include_examples "successful TLS connection"
214
+
215
+ describe "TLS connection to RabbitMQ with client certificates provided inline", skip: ENV["CI"] do
216
+ let(:subject) do
217
+ c = Bunny.new(
218
+ hostname: local_hostname(),
219
+ username: "bunny_gem",
220
+ password: "bunny_password",
221
+ vhost: "bunny_testbed",
222
+ tls: true,
223
+ tls_cert: File.read("#{CERTIFICATE_DIR}/client_certificate.pem"),
224
+ tls_key: File.read("#{CERTIFICATE_DIR}/client_key.pem"),
225
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
226
+ verify_peer: false)
227
+ c.start
228
+ c
223
229
  end
224
230
 
225
- describe "TLS connection to RabbitMQ with tls_version TLSv1.1 specified" do
226
- let(:subject) do
227
- c = Bunny.new(
228
- hostname: local_hostname(),
229
- username: "bunny_gem",
230
- password: "bunny_password",
231
- vhost: "bunny_testbed",
232
- tls: true,
233
- tls_protocol: :TLSv1_1,
234
- tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
235
- verify_peer: false)
236
- c.start
237
- c
238
- end
231
+ after :each do
232
+ subject.close
233
+ end
239
234
 
240
- after :each do
241
- subject.close
242
- end
235
+ include_examples "successful TLS connection"
236
+ end
243
237
 
244
- include_examples "successful TLS connection"
238
+ describe "TLS connection to RabbitMQ with tls_version TLSv1.2 specified", skip: ENV["CI"] do
239
+ let(:subject) do
240
+ c = Bunny.new(
241
+ hostname: local_hostname(),
242
+ username: "bunny_gem",
243
+ password: "bunny_password",
244
+ vhost: "bunny_testbed",
245
+ tls: true,
246
+ tls_protocol: :TLSv1_2,
247
+ tls_ca_certificates: ["#{CERTIFICATE_DIR}/ca_certificate.pem"],
248
+ verify_peer: false)
249
+ c.start
250
+ c
251
+ end
245
252
 
246
- it "connects using TLSv1.1" do
247
- expect(subject.transport.socket.ssl_version).to eq "TLSv1.1"
248
- end
253
+ after :each do
254
+ subject.close
255
+ end
256
+
257
+ include_examples "successful TLS connection"
258
+
259
+ it "connects using TLSv1.2", skip: no_tls12_supported? do
260
+ expect(subject.transport.socket.ssl_version).to eq "TLSv1.2"
249
261
  end
250
262
  end
@@ -4,7 +4,7 @@ describe Bunny::Session do
4
4
  context "with unreachable host" do
5
5
  it "raises Bunny::TCPConnectionFailed" do
6
6
  begin
7
- conn = Bunny.new(:hostname => "192.192.192.192")
7
+ conn = Bunny.new(:hostname => "127.0.0.254", :port => 1433)
8
8
  conn.start
9
9
 
10
10
  fail "expected 192.192.192.192 to be unreachable"
@@ -24,7 +24,7 @@ unless ENV["CI"]
24
24
  ch2 = @connection1.create_channel
25
25
 
26
26
  q = ch1.queue("", exclusive: true)
27
- q.subscribe(manual_ack: false, block: false) do |delivery_info, properties, payload|
27
+ q.subscribe(manual_ack: false) do |delivery_info, properties, payload|
28
28
  delivered_data << payload
29
29
  end
30
30
  sleep 0.5
@@ -57,7 +57,7 @@ unless ENV["CI"]
57
57
  sleep 0.7
58
58
  expect(q.message_count).to eq 3
59
59
 
60
- q.subscribe(manual_ack: false, block: false) do |delivery_info, properties, payload|
60
+ q.subscribe(manual_ack: false) do |delivery_info, properties, payload|
61
61
  delivered_data << payload
62
62
  end
63
63
  sleep 0.7
@@ -1,5 +1,5 @@
1
- require_relative '../../lib/bunny/channel'
2
- require_relative '../../lib/bunny/exchange'
1
+ require 'bunny/channel'
2
+ require 'bunny/exchange'
3
3
 
4
4
  module Bunny
5
5
  describe Exchange do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.2
4
+ version: 2.16.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Duncan
@@ -12,31 +12,32 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2019-04-24 00:00:00.000000000 Z
15
+ date: 2020-08-14 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: amq-protocol
19
19
  requirement: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 2.3.0
24
21
  - - "~>"
25
22
  - !ruby/object:Gem::Version
26
23
  version: '2.3'
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.1
27
27
  type: :runtime
28
28
  prerelease: false
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 2.3.0
34
31
  - - "~>"
35
32
  - !ruby/object:Gem::Version
36
33
  version: '2.3'
37
- description: Easy to use, feature complete Ruby client for RabbitMQ
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.3.1
37
+ description: Easy to use, feature complete Ruby client for RabbitMQ 3.3 and later
38
+ versions.
38
39
  email:
39
- - mklishin@pivotal.io
40
+ - michael.s.klishin@gmail.com
40
41
  executables: []
41
42
  extensions: []
42
43
  extra_rdoc_files:
@@ -240,10 +241,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
240
241
  - !ruby/object:Gem::Version
241
242
  version: '0'
242
243
  requirements: []
243
- rubygems_version: 3.0.3
244
+ rubygems_version: 3.1.2
244
245
  signing_key:
245
246
  specification_version: 4
246
- summary: Easy to use Ruby client for RabbitMQ
247
+ summary: Popular easy to use Ruby client for RabbitMQ
247
248
  test_files:
248
249
  - spec/config/enabled_plugins
249
250
  - spec/config/rabbitmq.conf