bunny 1.3.0 → 2.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.gitignore +7 -1
- data/.rspec +1 -3
- data/.travis.yml +21 -14
- data/CONTRIBUTING.md +132 -0
- data/ChangeLog.md +887 -1
- data/Gemfile +13 -13
- data/LICENSE +1 -1
- data/README.md +46 -60
- data/Rakefile +54 -0
- data/bunny.gemspec +5 -11
- 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/extensions/basic_nack.rb +1 -1
- data/examples/guides/extensions/dead_letter_exchange.rb +1 -1
- 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 +4 -2
- data/lib/bunny.rb +8 -4
- data/lib/bunny/channel.rb +268 -153
- 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 +48 -21
- data/lib/bunny/cruby/ssl_socket.rb +65 -4
- data/lib/bunny/exceptions.rb +25 -4
- data/lib/bunny/exchange.rb +24 -28
- 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 +31 -22
- data/lib/bunny/reader_loop.rb +31 -18
- data/lib/bunny/session.rb +448 -159
- data/lib/bunny/test_kit.rb +14 -0
- data/lib/bunny/timeout.rb +1 -12
- data/lib/bunny/transport.rb +205 -98
- data/lib/bunny/version.rb +1 -1
- data/repl +1 -1
- data/spec/config/enabled_plugins +1 -0
- data/spec/config/rabbitmq.conf +13 -0
- data/spec/higher_level_api/integration/basic_ack_spec.rb +175 -16
- 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 +424 -221
- data/spec/higher_level_api/integration/connection_spec.rb +300 -126
- 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 +34 -11
- 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 +26 -8
- 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 +156 -42
- 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 +224 -89
- 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 -11
- data/spec/issues/issue141_spec.rb +13 -14
- data/spec/issues/issue202_spec.rb +1 -1
- data/spec/issues/issue224_spec.rb +40 -0
- 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 +8 -26
- data/spec/stress/channel_close_stress_spec.rb +64 -0
- data/spec/stress/channel_open_stress_spec.rb +15 -9
- 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/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_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 +65 -47
- data/.ruby-version +0 -1
- data/lib/bunny/compatibility.rb +0 -24
- data/lib/bunny/system_timer.rb +0 -20
- data/spec/compatibility/queue_declare_spec.rb +0 -44
- data/spec/compatibility/queue_declare_with_default_channel_spec.rb +0 -33
- 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,23 +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
|
-
|
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
|
15
27
|
|
16
28
|
def self.open(host, port, options = {})
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
25
37
|
end
|
38
|
+
socket.extend self
|
39
|
+
socket.options = { :host => host, :port => port }.merge(options)
|
40
|
+
socket
|
41
|
+
rescue Errno::ETIMEDOUT
|
42
|
+
raise ClientTimeout
|
26
43
|
end
|
27
44
|
|
28
45
|
# Reads given number of bytes with an optional timeout
|
@@ -62,22 +79,32 @@ module Bunny
|
|
62
79
|
# if this is not appropriate in your case.
|
63
80
|
#
|
64
81
|
# @param [String] data Data to write
|
82
|
+
# @param [Integer] timeout Timeout
|
65
83
|
#
|
66
84
|
# @api public
|
67
|
-
def write_nonblock_fully(data)
|
85
|
+
def write_nonblock_fully(data, timeout = nil)
|
68
86
|
return nil if @__bunny_socket_eof_flag__
|
69
87
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
88
|
+
length = data.bytesize
|
89
|
+
total_count = 0
|
90
|
+
count = 0
|
91
|
+
loop do
|
92
|
+
begin
|
93
|
+
count = self.write_nonblock(data)
|
94
|
+
rescue *WRITE_RETRY_EXCEPTION_CLASSES
|
95
|
+
if IO.select([], [self], nil, timeout)
|
96
|
+
retry
|
97
|
+
else
|
98
|
+
raise Timeout::Error, "IO timeout when writing to socket"
|
99
|
+
end
|
74
100
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
101
|
+
|
102
|
+
total_count += count
|
103
|
+
return total_count if total_count >= length
|
104
|
+
data = data.byteslice(count..-1)
|
78
105
|
end
|
79
106
|
|
80
|
-
data.bytesize
|
81
107
|
end
|
108
|
+
|
82
109
|
end
|
83
110
|
end
|
@@ -8,10 +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
|
|
27
|
+
def initialize(*args)
|
28
|
+
super
|
29
|
+
@__bunny_socket_eof_flag__ = false
|
30
|
+
end
|
15
31
|
|
16
32
|
# Reads given number of bytes with an optional timeout
|
17
33
|
#
|
@@ -50,8 +66,53 @@ module Bunny
|
|
50
66
|
end
|
51
67
|
value
|
52
68
|
end
|
69
|
+
|
70
|
+
# Writes provided data using IO#write_nonblock, taking care of handling
|
71
|
+
# of exceptions it raises when writing would fail (e.g. due to socket buffer
|
72
|
+
# being full).
|
73
|
+
#
|
74
|
+
# IMPORTANT: this method will mutate (slice) the argument. Pass in duplicates
|
75
|
+
# if this is not appropriate in your case.
|
76
|
+
#
|
77
|
+
# @param [String] data Data to write
|
78
|
+
# @param [Integer] timeout Timeout
|
79
|
+
#
|
80
|
+
# @api public
|
81
|
+
def write_nonblock_fully(data, timeout = nil)
|
82
|
+
return nil if @__bunny_socket_eof_flag__
|
83
|
+
|
84
|
+
length = data.bytesize
|
85
|
+
total_count = 0
|
86
|
+
count = 0
|
87
|
+
loop do
|
88
|
+
begin
|
89
|
+
count = self.write_nonblock(data)
|
90
|
+
rescue OpenSSL::SSL::SSLError => e
|
91
|
+
if e.message == "write would block"
|
92
|
+
if IO.select([], [self], nil, timeout)
|
93
|
+
retry
|
94
|
+
else
|
95
|
+
raise Timeout::Error, "IO timeout when writing to socket"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
raise e
|
99
|
+
rescue *WRITE_RETRY_EXCEPTION_CLASSES
|
100
|
+
if IO.select([], [self], nil, timeout)
|
101
|
+
retry
|
102
|
+
else
|
103
|
+
raise Timeout::Error, "IO timeout when writing to socket"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
total_count += count
|
108
|
+
return total_count if total_count >= length
|
109
|
+
data = data.byteslice(count..-1)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
53
114
|
end
|
54
|
-
rescue LoadError
|
115
|
+
rescue LoadError
|
55
116
|
puts "Could not load OpenSSL"
|
56
117
|
end
|
57
118
|
end
|
data/lib/bunny/exceptions.rb
CHANGED
@@ -4,6 +4,12 @@ module Bunny
|
|
4
4
|
class Exception < ::StandardError
|
5
5
|
end
|
6
6
|
|
7
|
+
class HostListDepleted < Exception
|
8
|
+
def initialize
|
9
|
+
super("No more hosts to try in the supplied list of hosts")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
# Indicates a network failure. If automatic network
|
8
14
|
# recovery mode is enabled, these will be typically handled
|
9
15
|
# by the client itself.
|
@@ -54,20 +60,29 @@ module Bunny
|
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
57
|
-
|
58
63
|
# Raised when TCP connection to RabbitMQ fails because of an unresolved
|
59
64
|
# hostname, connectivity problem, etc
|
60
65
|
class TCPConnectionFailed < Exception
|
61
66
|
attr_reader :hostname, :port
|
62
67
|
|
63
|
-
def initialize(e, hostname, port)
|
68
|
+
def initialize(e, hostname=nil, port=nil)
|
64
69
|
m = case e
|
65
70
|
when String then
|
66
71
|
e
|
67
|
-
when Exception then
|
72
|
+
when ::Exception then
|
68
73
|
e.message
|
69
74
|
end
|
70
|
-
|
75
|
+
if hostname && port
|
76
|
+
super("Could not establish TCP connection to #{hostname}:#{port}: #{m}")
|
77
|
+
else
|
78
|
+
super(m)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class TCPConnectionFailedForAllHosts < TCPConnectionFailed
|
84
|
+
def initialize
|
85
|
+
super("Could not establish TCP connection to any of the configured hosts", nil, nil)
|
71
86
|
end
|
72
87
|
end
|
73
88
|
|
@@ -82,6 +97,12 @@ module Bunny
|
|
82
97
|
end
|
83
98
|
end
|
84
99
|
|
100
|
+
class ConnectionAlreadyClosed < Exception
|
101
|
+
def initialize
|
102
|
+
super('Connection has been already closed')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
85
106
|
class ShutdownSignal < Exception
|
86
107
|
end
|
87
108
|
|