bunny 1.7.0 → 2.17.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 +5 -5
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.gitignore +6 -1
- data/.rspec +1 -3
- data/.travis.yml +21 -14
- data/CONTRIBUTING.md +132 -0
- data/ChangeLog.md +745 -1
- data/Gemfile +13 -13
- data/LICENSE +1 -1
- data/README.md +41 -75
- data/Rakefile +54 -0
- data/bunny.gemspec +4 -10
- data/docker-compose.yml +28 -0
- data/docker/Dockerfile +24 -0
- data/docker/apt/preferences.d/erlang +3 -0
- data/docker/apt/sources.list.d/bintray.rabbitmq.list +2 -0
- data/docker/docker-entrypoint.sh +26 -0
- data/docker/rabbitmq.conf +29 -0
- data/examples/connection/automatic_recovery_with_basic_get.rb +1 -1
- data/examples/connection/automatic_recovery_with_client_named_queues.rb +1 -1
- data/examples/connection/automatic_recovery_with_multiple_consumers.rb +1 -1
- data/examples/connection/automatic_recovery_with_republishing.rb +1 -1
- data/examples/connection/automatic_recovery_with_server_named_queues.rb +1 -1
- data/examples/connection/channel_level_exception.rb +1 -9
- data/examples/connection/disabled_automatic_recovery.rb +1 -1
- data/examples/connection/heartbeat.rb +1 -1
- data/examples/consumers/high_and_low_priority.rb +1 -1
- data/examples/guides/extensions/alternate_exchange.rb +2 -0
- data/examples/guides/getting_started/hello_world.rb +2 -0
- data/examples/guides/getting_started/weathr.rb +2 -0
- data/examples/guides/queues/one_off_consumer.rb +2 -0
- data/examples/guides/queues/redeliveries.rb +2 -0
- data/lib/bunny.rb +6 -2
- data/lib/bunny/channel.rb +192 -109
- data/lib/bunny/channel_id_allocator.rb +6 -4
- data/lib/bunny/concurrent/continuation_queue.rb +34 -13
- data/lib/bunny/consumer_work_pool.rb +34 -6
- data/lib/bunny/cruby/socket.rb +29 -16
- data/lib/bunny/cruby/ssl_socket.rb +20 -7
- data/lib/bunny/exceptions.rb +7 -1
- data/lib/bunny/exchange.rb +11 -7
- data/lib/bunny/get_response.rb +1 -1
- data/lib/bunny/heartbeat_sender.rb +3 -2
- data/lib/bunny/jruby/socket.rb +23 -6
- data/lib/bunny/jruby/ssl_socket.rb +5 -0
- data/lib/bunny/queue.rb +12 -10
- data/lib/bunny/reader_loop.rb +31 -18
- data/lib/bunny/session.rb +389 -134
- data/lib/bunny/test_kit.rb +14 -0
- data/lib/bunny/timeout.rb +1 -12
- data/lib/bunny/transport.rb +114 -67
- data/lib/bunny/version.rb +1 -1
- data/repl +1 -1
- data/spec/config/rabbitmq.conf +13 -0
- data/spec/higher_level_api/integration/basic_ack_spec.rb +154 -22
- data/spec/higher_level_api/integration/basic_cancel_spec.rb +77 -11
- data/spec/higher_level_api/integration/basic_consume_spec.rb +60 -55
- data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +6 -6
- data/spec/higher_level_api/integration/basic_get_spec.rb +31 -7
- data/spec/higher_level_api/integration/basic_nack_spec.rb +22 -19
- data/spec/higher_level_api/integration/basic_publish_spec.rb +11 -100
- data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -4
- data/spec/higher_level_api/integration/basic_reject_spec.rb +94 -16
- data/spec/higher_level_api/integration/basic_return_spec.rb +4 -4
- data/spec/higher_level_api/integration/channel_close_spec.rb +51 -10
- data/spec/higher_level_api/integration/channel_open_spec.rb +12 -12
- data/spec/higher_level_api/integration/connection_recovery_spec.rb +412 -286
- data/spec/higher_level_api/integration/connection_spec.rb +284 -134
- data/spec/higher_level_api/integration/connection_stop_spec.rb +31 -19
- data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +17 -17
- data/spec/higher_level_api/integration/dead_lettering_spec.rb +14 -14
- data/spec/higher_level_api/integration/exchange_bind_spec.rb +5 -5
- data/spec/higher_level_api/integration/exchange_declare_spec.rb +32 -31
- data/spec/higher_level_api/integration/exchange_delete_spec.rb +12 -12
- data/spec/higher_level_api/integration/exchange_unbind_spec.rb +5 -5
- data/spec/higher_level_api/integration/exclusive_queue_spec.rb +5 -5
- data/spec/higher_level_api/integration/heartbeat_spec.rb +4 -4
- data/spec/higher_level_api/integration/message_properties_access_spec.rb +49 -49
- data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +2 -2
- data/spec/higher_level_api/integration/publisher_confirms_spec.rb +92 -27
- data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +19 -19
- data/spec/higher_level_api/integration/queue_bind_spec.rb +23 -23
- data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -34
- data/spec/higher_level_api/integration/queue_delete_spec.rb +2 -2
- data/spec/higher_level_api/integration/queue_purge_spec.rb +5 -5
- data/spec/higher_level_api/integration/queue_unbind_spec.rb +6 -6
- data/spec/higher_level_api/integration/read_only_consumer_spec.rb +9 -9
- data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +10 -10
- data/spec/higher_level_api/integration/tls_connection_spec.rb +218 -112
- data/spec/higher_level_api/integration/toxiproxy_spec.rb +76 -0
- data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
- data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
- data/spec/higher_level_api/integration/with_channel_spec.rb +2 -2
- data/spec/issues/issue100_spec.rb +11 -12
- data/spec/issues/issue141_spec.rb +13 -14
- data/spec/issues/issue202_spec.rb +1 -1
- data/spec/issues/issue224_spec.rb +5 -5
- data/spec/issues/issue465_spec.rb +32 -0
- data/spec/issues/issue549_spec.rb +30 -0
- data/spec/issues/issue78_spec.rb +21 -24
- data/spec/issues/issue83_spec.rb +5 -6
- data/spec/issues/issue97_spec.rb +44 -45
- data/spec/lower_level_api/integration/basic_cancel_spec.rb +15 -16
- data/spec/lower_level_api/integration/basic_consume_spec.rb +20 -21
- data/spec/spec_helper.rb +2 -19
- data/spec/stress/channel_close_stress_spec.rb +3 -3
- data/spec/stress/channel_open_stress_spec.rb +4 -4
- data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +7 -7
- data/spec/stress/concurrent_consumers_stress_spec.rb +18 -16
- data/spec/stress/concurrent_publishers_stress_spec.rb +16 -19
- data/spec/stress/connection_open_close_spec.rb +9 -9
- data/spec/stress/merry_go_round_spec.rb +105 -0
- data/spec/tls/ca_certificate.pem +27 -16
- data/spec/tls/ca_key.pem +52 -27
- data/spec/tls/client_certificate.pem +27 -16
- data/spec/tls/client_key.pem +49 -25
- data/spec/tls/generate-server-cert.sh +8 -0
- data/spec/tls/server-openssl.cnf +10 -0
- data/spec/tls/server.csr +16 -0
- data/spec/tls/server_certificate.pem +27 -16
- data/spec/tls/server_key.pem +49 -25
- data/spec/toxiproxy_helper.rb +28 -0
- data/spec/unit/bunny_spec.rb +5 -5
- data/spec/unit/concurrent/atomic_fixnum_spec.rb +6 -6
- data/spec/unit/concurrent/condition_spec.rb +8 -8
- data/spec/unit/concurrent/linked_continuation_queue_spec.rb +2 -2
- data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +16 -16
- data/spec/unit/exchange_recovery_spec.rb +39 -0
- data/spec/unit/version_delivery_tag_spec.rb +3 -3
- metadata +42 -35
- data/lib/bunny/system_timer.rb +0 -20
- data/spec/config/rabbitmq.config +0 -18
- data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
- data/spec/higher_level_api/integration/confirm_select_spec.rb +0 -19
- data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -50
- data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
- data/spec/stress/long_running_consumer_spec.rb +0 -83
- data/spec/tls/cacert.pem +0 -18
- data/spec/tls/client_cert.pem +0 -18
- data/spec/tls/server_cert.pem +0 -18
- data/spec/unit/system_timer_spec.rb +0 -10
@@ -17,7 +17,9 @@ module Bunny
|
|
17
17
|
#
|
18
18
|
|
19
19
|
# @param [Integer] max_channel Max allowed channel id
|
20
|
-
def initialize(max_channel = ((1 <<
|
20
|
+
def initialize(max_channel = ((1 << 11) - 1))
|
21
|
+
# channel 0 has special meaning in the protocol, so start
|
22
|
+
# allocator at 1
|
21
23
|
@allocator = AMQ::IntAllocator.new(1, max_channel)
|
22
24
|
@mutex = Monitor.new
|
23
25
|
end
|
@@ -25,7 +27,7 @@ module Bunny
|
|
25
27
|
|
26
28
|
# Returns next available channel id. This method is thread safe.
|
27
29
|
#
|
28
|
-
# @return [
|
30
|
+
# @return [Integer]
|
29
31
|
# @api public
|
30
32
|
# @see ChannelManager#release_channel_id
|
31
33
|
# @see ChannelManager#reset_channel_id_allocator
|
@@ -37,7 +39,7 @@ module Bunny
|
|
37
39
|
|
38
40
|
# Releases previously allocated channel id. This method is thread safe.
|
39
41
|
#
|
40
|
-
# @param [
|
42
|
+
# @param [Integer] i Channel id to release
|
41
43
|
# @api public
|
42
44
|
# @see ChannelManager#next_channel_id
|
43
45
|
# @see ChannelManager#reset_channel_id_allocator
|
@@ -51,7 +53,7 @@ module Bunny
|
|
51
53
|
# Returns true if given channel id has been previously allocated and not yet released.
|
52
54
|
# This method is thread safe.
|
53
55
|
#
|
54
|
-
# @param [
|
56
|
+
# @param [Integer] i Channel id to check
|
55
57
|
# @return [Boolean] true if given channel id has been previously allocated and not yet released
|
56
58
|
# @api public
|
57
59
|
# @see ChannelManager#next_channel_id
|
@@ -6,36 +6,57 @@ module Bunny
|
|
6
6
|
#
|
7
7
|
# @private
|
8
8
|
class ContinuationQueue
|
9
|
-
def initialize
|
10
|
-
@q
|
9
|
+
def initialize
|
10
|
+
@q = []
|
11
|
+
@lock = ::Mutex.new
|
12
|
+
@cond = ::ConditionVariable.new
|
11
13
|
end
|
12
14
|
|
13
|
-
def push(
|
14
|
-
@
|
15
|
+
def push(item)
|
16
|
+
@lock.synchronize do
|
17
|
+
@q.push(item)
|
18
|
+
@cond.signal
|
19
|
+
end
|
15
20
|
end
|
16
21
|
alias << push
|
17
22
|
|
18
23
|
def pop
|
19
|
-
|
24
|
+
poll
|
20
25
|
end
|
21
26
|
|
22
27
|
def poll(timeout_in_ms = nil)
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
timeout = timeout_in_ms ? timeout_in_ms / 1000.0 : nil
|
29
|
+
|
30
|
+
@lock.synchronize do
|
31
|
+
timeout_strikes_at = Time.now.utc + (timeout || 0)
|
32
|
+
while @q.empty?
|
33
|
+
wait = if timeout
|
34
|
+
timeout_strikes_at - Time.now.utc
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
@cond.wait(@lock, wait)
|
39
|
+
raise ::Timeout::Error if wait && Time.now.utc >= timeout_strikes_at
|
26
40
|
end
|
27
|
-
|
28
|
-
|
41
|
+
item = @q.shift
|
42
|
+
item
|
29
43
|
end
|
30
44
|
end
|
31
45
|
|
32
46
|
def clear
|
33
|
-
@
|
47
|
+
@lock.synchronize do
|
48
|
+
@q.clear
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def empty?
|
53
|
+
@q.empty?
|
34
54
|
end
|
35
55
|
|
36
|
-
def
|
37
|
-
@q.
|
56
|
+
def size
|
57
|
+
@q.size
|
38
58
|
end
|
59
|
+
alias length size
|
39
60
|
end
|
40
61
|
end
|
41
62
|
end
|
@@ -15,10 +15,17 @@ module Bunny
|
|
15
15
|
|
16
16
|
attr_reader :threads
|
17
17
|
attr_reader :size
|
18
|
+
attr_reader :abort_on_exception
|
18
19
|
|
19
|
-
def initialize(size = 1)
|
20
|
+
def initialize(size = 1, abort_on_exception = false, shutdown_timeout = 60)
|
20
21
|
@size = size
|
22
|
+
@abort_on_exception = abort_on_exception
|
23
|
+
@shutdown_timeout = shutdown_timeout
|
24
|
+
@shutdown_mutex = ::Mutex.new
|
25
|
+
@shutdown_conditional = ::ConditionVariable.new
|
21
26
|
@queue = ::Queue.new
|
27
|
+
@paused = false
|
28
|
+
@running = false
|
22
29
|
end
|
23
30
|
|
24
31
|
|
@@ -31,6 +38,7 @@ module Bunny
|
|
31
38
|
|
32
39
|
@size.times do
|
33
40
|
t = Thread.new(&method(:run_loop))
|
41
|
+
t.abort_on_exception = true if abort_on_exception
|
34
42
|
@threads << t
|
35
43
|
end
|
36
44
|
|
@@ -41,7 +49,16 @@ module Bunny
|
|
41
49
|
@running
|
42
50
|
end
|
43
51
|
|
44
|
-
def
|
52
|
+
def backlog
|
53
|
+
@queue.length
|
54
|
+
end
|
55
|
+
|
56
|
+
def busy?
|
57
|
+
!@queue.empty?
|
58
|
+
end
|
59
|
+
|
60
|
+
def shutdown(wait_for_workers = false)
|
61
|
+
was_running = running?
|
45
62
|
@running = false
|
46
63
|
|
47
64
|
@size.times do
|
@@ -49,20 +66,26 @@ module Bunny
|
|
49
66
|
throw :terminate
|
50
67
|
end
|
51
68
|
end
|
69
|
+
|
70
|
+
return if !(wait_for_workers && @shutdown_timeout && was_running)
|
71
|
+
|
72
|
+
@shutdown_mutex.synchronize do
|
73
|
+
@shutdown_conditional.wait(@shutdown_mutex, @shutdown_timeout)
|
74
|
+
end
|
52
75
|
end
|
53
76
|
|
54
77
|
def join(timeout = nil)
|
55
|
-
@threads.each { |t| t.join(timeout) }
|
78
|
+
(@threads || []).each { |t| t.join(timeout) }
|
56
79
|
end
|
57
80
|
|
58
81
|
def pause
|
59
82
|
@running = false
|
60
|
-
|
61
|
-
@threads.each { |t| t.stop }
|
83
|
+
@paused = true
|
62
84
|
end
|
63
85
|
|
64
86
|
def resume
|
65
87
|
@running = true
|
88
|
+
@paused = false
|
66
89
|
|
67
90
|
@threads.each { |t| t.run }
|
68
91
|
end
|
@@ -70,7 +93,7 @@ module Bunny
|
|
70
93
|
def kill
|
71
94
|
@running = false
|
72
95
|
|
73
|
-
@threads.each { |t| t.kill }
|
96
|
+
(@threads || []).each { |t| t.kill }
|
74
97
|
end
|
75
98
|
|
76
99
|
protected
|
@@ -78,6 +101,7 @@ module Bunny
|
|
78
101
|
def run_loop
|
79
102
|
catch(:terminate) do
|
80
103
|
loop do
|
104
|
+
Thread.stop if @paused
|
81
105
|
callable = @queue.pop
|
82
106
|
|
83
107
|
begin
|
@@ -89,6 +113,10 @@ module Bunny
|
|
89
113
|
end
|
90
114
|
end
|
91
115
|
end
|
116
|
+
|
117
|
+
@shutdown_mutex.synchronize do
|
118
|
+
@shutdown_conditional.signal unless busy?
|
119
|
+
end
|
92
120
|
end
|
93
121
|
end
|
94
122
|
end
|
data/lib/bunny/cruby/socket.rb
CHANGED
@@ -6,27 +6,40 @@ module Bunny
|
|
6
6
|
#
|
7
7
|
# Heavily inspired by Dalli by Mike Perham.
|
8
8
|
# @private
|
9
|
-
|
9
|
+
module Socket
|
10
10
|
attr_accessor :options
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
READ_RETRY_EXCEPTION_CLASSES = if defined?(IO::EAGAINWaitReadable)
|
13
|
+
# Ruby 2.1+
|
14
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable,
|
15
|
+
IO::EAGAINWaitReadable, IO::EWOULDBLOCKWaitReadable]
|
16
|
+
else
|
17
|
+
# 2.0
|
18
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable]
|
19
|
+
end
|
20
|
+
WRITE_RETRY_EXCEPTION_CLASSES = if defined?(IO::EAGAINWaitWritable)
|
21
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable,
|
22
|
+
IO::EAGAINWaitWritable, IO::EWOULDBLOCKWaitWritable]
|
23
|
+
else
|
24
|
+
# 2.0
|
25
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable]
|
26
|
+
end
|
19
27
|
|
20
28
|
def self.open(host, port, options = {})
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
socket = ::Socket.tcp(host, port, nil, nil,
|
30
|
+
connect_timeout: options[:connect_timeout])
|
31
|
+
if ::Socket.constants.include?('TCP_NODELAY') || ::Socket.constants.include?(:TCP_NODELAY)
|
32
|
+
socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
|
33
|
+
end
|
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
|
29
37
|
end
|
38
|
+
socket.extend self
|
39
|
+
socket.options = { :host => host, :port => port }.merge(options)
|
40
|
+
socket
|
41
|
+
rescue Errno::ETIMEDOUT
|
42
|
+
raise ClientTimeout
|
30
43
|
end
|
31
44
|
|
32
45
|
# Reads given number of bytes with an optional timeout
|
@@ -8,13 +8,26 @@ module Bunny
|
|
8
8
|
# methods found in Bunny::Socket.
|
9
9
|
class SSLSocket < OpenSSL::SSL::SSLSocket
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
READ_RETRY_EXCEPTION_CLASSES = if defined?(IO::EAGAINWaitReadable)
|
12
|
+
# Ruby 2.1+
|
13
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable,
|
14
|
+
IO::EAGAINWaitReadable, IO::EWOULDBLOCKWaitReadable]
|
15
|
+
else
|
16
|
+
# 2.0
|
17
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable]
|
18
|
+
end
|
19
|
+
WRITE_RETRY_EXCEPTION_CLASSES = if defined?(IO::EAGAINWaitWritable)
|
20
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable,
|
21
|
+
IO::EAGAINWaitWritable, IO::EWOULDBLOCKWaitWritable]
|
22
|
+
else
|
23
|
+
# 2.0
|
24
|
+
[Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable]
|
25
|
+
end
|
14
26
|
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
def initialize(*args)
|
28
|
+
super
|
29
|
+
@__bunny_socket_eof_flag__ = false
|
30
|
+
end
|
18
31
|
|
19
32
|
# Reads given number of bytes with an optional timeout
|
20
33
|
#
|
@@ -99,7 +112,7 @@ module Bunny
|
|
99
112
|
end
|
100
113
|
|
101
114
|
end
|
102
|
-
rescue LoadError
|
115
|
+
rescue LoadError
|
103
116
|
puts "Could not load OpenSSL"
|
104
117
|
end
|
105
118
|
end
|
data/lib/bunny/exceptions.rb
CHANGED
@@ -69,7 +69,7 @@ module Bunny
|
|
69
69
|
m = case e
|
70
70
|
when String then
|
71
71
|
e
|
72
|
-
when Exception then
|
72
|
+
when ::Exception then
|
73
73
|
e.message
|
74
74
|
end
|
75
75
|
if hostname && port
|
@@ -97,6 +97,12 @@ module Bunny
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
class ConnectionAlreadyClosed < Exception
|
101
|
+
def initialize
|
102
|
+
super('Connection has been already closed')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
100
106
|
class ShutdownSignal < Exception
|
101
107
|
end
|
102
108
|
|
data/lib/bunny/exchange.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'amq/protocol'
|
2
|
+
|
1
3
|
module Bunny
|
2
4
|
# Represents AMQP 0.9.1 exchanges.
|
3
5
|
#
|
@@ -80,6 +82,8 @@ module Bunny
|
|
80
82
|
@internal = @options[:internal]
|
81
83
|
@arguments = @options[:arguments]
|
82
84
|
|
85
|
+
@bindings = Set.new
|
86
|
+
|
83
87
|
declare! unless opts[:no_declare] || predeclared? || (@name == AMQ::Protocol::EMPTY_STRING)
|
84
88
|
|
85
89
|
@channel.register_exchange(self)
|
@@ -169,6 +173,7 @@ module Bunny
|
|
169
173
|
# @api public
|
170
174
|
def bind(source, opts = {})
|
171
175
|
@channel.exchange_bind(source, self, opts)
|
176
|
+
@bindings.add(source: source, opts: opts)
|
172
177
|
|
173
178
|
self
|
174
179
|
end
|
@@ -189,6 +194,7 @@ module Bunny
|
|
189
194
|
# @api public
|
190
195
|
def unbind(source, opts = {})
|
191
196
|
@channel.exchange_unbind(source, self, opts)
|
197
|
+
@bindings.delete(source: source, opts: opts)
|
192
198
|
|
193
199
|
self
|
194
200
|
end
|
@@ -214,8 +220,11 @@ module Bunny
|
|
214
220
|
|
215
221
|
# @private
|
216
222
|
def recover_from_network_failure
|
217
|
-
|
218
|
-
|
223
|
+
declare! unless @options[:no_declare] ||predefined?
|
224
|
+
|
225
|
+
@bindings.each do |b|
|
226
|
+
bind(b[:source], b[:opts])
|
227
|
+
end
|
219
228
|
end
|
220
229
|
|
221
230
|
|
@@ -245,11 +254,6 @@ module Bunny
|
|
245
254
|
@channel.exchange_declare(@name, @type, @options)
|
246
255
|
end
|
247
256
|
|
248
|
-
# @private
|
249
|
-
def self.add_default_options(name, opts, block)
|
250
|
-
{ :exchange => name, :nowait => (block.nil? && !name.empty?) }.merge(opts)
|
251
|
-
end
|
252
|
-
|
253
257
|
# @private
|
254
258
|
def self.add_default_options(name, opts)
|
255
259
|
# :nowait is always false for Bunny
|
data/lib/bunny/get_response.rb
CHANGED
@@ -29,6 +29,7 @@ module Bunny
|
|
29
29
|
@interval = [(period / 2) - 1, 0.4].max
|
30
30
|
|
31
31
|
@thread = Thread.new(&method(:run))
|
32
|
+
@thread.report_on_exception = false if @thread.respond_to?(:report_on_exception)
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
@@ -62,8 +63,8 @@ module Bunny
|
|
62
63
|
now = Time.now
|
63
64
|
|
64
65
|
if now > (@last_activity_time + @interval)
|
65
|
-
@logger.debug "Sending a heartbeat, last activity time: #{@last_activity_time}, interval (s): #{@interval}"
|
66
|
-
@transport.write_without_timeout(AMQ::Protocol::HeartbeatFrame.encode)
|
66
|
+
@logger.debug { "Sending a heartbeat, last activity time: #{@last_activity_time}, interval (s): #{@interval}" }
|
67
|
+
@transport.write_without_timeout(AMQ::Protocol::HeartbeatFrame.encode, true)
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
data/lib/bunny/jruby/socket.rb
CHANGED
@@ -5,7 +5,22 @@ module Bunny
|
|
5
5
|
# TCP socket extension that uses Socket#readpartial to avoid excessive CPU
|
6
6
|
# burn after some time. See issue #165.
|
7
7
|
# @private
|
8
|
-
|
8
|
+
module Socket
|
9
|
+
include Bunny::Socket
|
10
|
+
|
11
|
+
def self.open(host, port, options = {})
|
12
|
+
socket = ::Socket.tcp(host, port, nil, nil,
|
13
|
+
connect_timeout: options[:connect_timeout])
|
14
|
+
if ::Socket.constants.include?('TCP_NODELAY') || ::Socket.constants.include?(:TCP_NODELAY)
|
15
|
+
socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
|
16
|
+
end
|
17
|
+
socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options.fetch(:keepalive, true)
|
18
|
+
socket.extend self
|
19
|
+
socket.options = { :host => host, :port => port }.merge(options)
|
20
|
+
socket
|
21
|
+
rescue Errno::ETIMEDOUT
|
22
|
+
raise ClientTimeout
|
23
|
+
end
|
9
24
|
|
10
25
|
# Reads given number of bytes with an optional timeout
|
11
26
|
#
|
@@ -15,17 +30,17 @@ module Bunny
|
|
15
30
|
# @return [String] Data read from the socket
|
16
31
|
# @api public
|
17
32
|
def read_fully(count, timeout = nil)
|
18
|
-
return nil if @__bunny_socket_eof_flag__
|
19
|
-
|
20
33
|
value = ''
|
34
|
+
|
21
35
|
begin
|
22
36
|
loop do
|
23
|
-
value <<
|
37
|
+
value << read_nonblock(count - value.bytesize)
|
24
38
|
break if value.bytesize >= count
|
25
39
|
end
|
26
40
|
rescue EOFError
|
27
|
-
#
|
28
|
-
|
41
|
+
# JRuby specific fix via https://github.com/jruby/jruby/issues/1694#issuecomment-54873532
|
42
|
+
IO.select([self], nil, nil, timeout)
|
43
|
+
retry
|
29
44
|
rescue *READ_RETRY_EXCEPTION_CLASSES
|
30
45
|
if IO.select([self], nil, nil, timeout)
|
31
46
|
retry
|
@@ -33,8 +48,10 @@ module Bunny
|
|
33
48
|
raise Timeout::Error, "IO timeout when reading #{count} bytes"
|
34
49
|
end
|
35
50
|
end
|
51
|
+
|
36
52
|
value
|
37
53
|
end # read_fully
|
54
|
+
|
38
55
|
end
|
39
56
|
end
|
40
57
|
end
|