amq-client 0.7.0.alpha34 → 0.7.0.alpha35
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/Gemfile +1 -1
- data/README.textile +1 -1
- data/bin/ci/before_build.sh +24 -0
- data/examples/eventmachine_adapter/extensions/rabbitmq/handling_confirm_select_ok.rb +2 -2
- data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +1 -1
- data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_unroutable_message.rb +1 -1
- data/lib/amq/client.rb +29 -17
- data/lib/amq/client/adapter.rb +8 -504
- data/lib/amq/client/adapters/coolio.rb +4 -282
- data/lib/amq/client/adapters/event_machine.rb +4 -382
- data/lib/amq/client/async/adapter.rb +517 -0
- data/lib/amq/client/async/adapters/coolio.rb +291 -0
- data/lib/amq/client/async/adapters/event_machine.rb +392 -0
- data/lib/amq/client/async/adapters/eventmachine.rb +1 -0
- data/lib/amq/client/async/callbacks.rb +71 -0
- data/lib/amq/client/async/channel.rb +385 -0
- data/lib/amq/client/async/entity.rb +66 -0
- data/lib/amq/client/async/exchange.rb +157 -0
- data/lib/amq/client/async/extensions/rabbitmq/basic.rb +38 -0
- data/lib/amq/client/async/extensions/rabbitmq/confirm.rb +248 -0
- data/lib/amq/client/async/queue.rb +455 -0
- data/lib/amq/client/callbacks.rb +6 -65
- data/lib/amq/client/channel.rb +4 -376
- data/lib/amq/client/entity.rb +6 -57
- data/lib/amq/client/exchange.rb +4 -148
- data/lib/amq/client/extensions/rabbitmq/basic.rb +4 -28
- data/lib/amq/client/extensions/rabbitmq/confirm.rb +5 -240
- data/lib/amq/client/queue.rb +5 -450
- data/lib/amq/client/version.rb +1 -1
- data/spec/unit/client_spec.rb +10 -30
- metadata +16 -22
@@ -1,289 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require "cool.io"
|
6
|
-
require "amq/client"
|
7
|
-
require "amq/client/framing/string/frame"
|
3
|
+
require "amq/client/async/adapters/coolio"
|
8
4
|
|
9
5
|
module AMQ
|
10
6
|
module Client
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
#
|
15
|
-
class CoolioClient
|
16
|
-
|
17
|
-
#
|
18
|
-
# Behaviors
|
19
|
-
#
|
20
|
-
|
21
|
-
include AMQ::Client::Adapter
|
22
|
-
|
23
|
-
|
24
|
-
#
|
25
|
-
# API
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
#
|
30
|
-
# Cool.io socket delegates most of its operations to the parent adapter.
|
31
|
-
# Thus, 99.9% of the time you don't need to deal with this class.
|
32
|
-
#
|
33
|
-
# @api private
|
34
|
-
# @private
|
35
|
-
class Socket < ::Coolio::TCPSocket
|
36
|
-
attr_accessor :adapter
|
37
|
-
|
38
|
-
# Connects to given host/port and sets parent adapter.
|
39
|
-
#
|
40
|
-
# @param [CoolioClient]
|
41
|
-
# @param [String]
|
42
|
-
# @param [Fixnum]
|
43
|
-
def self.connect(adapter, host, port)
|
44
|
-
socket = super(host, port)
|
45
|
-
socket.adapter = adapter
|
46
|
-
socket
|
47
|
-
end
|
48
|
-
|
49
|
-
# Triggers socket_connect callback
|
50
|
-
def on_connect
|
51
|
-
#puts "On connect"
|
52
|
-
adapter.socket_connected
|
53
|
-
end
|
54
|
-
|
55
|
-
# Triggers on_read callback
|
56
|
-
def on_read(data)
|
57
|
-
# puts "Received data"
|
58
|
-
# puts_data(data)
|
59
|
-
adapter.receive_data(data)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Triggers socket_disconnect callback
|
63
|
-
def on_close
|
64
|
-
adapter.socket_disconnected
|
65
|
-
end
|
66
|
-
|
67
|
-
# Triggers tcp_connection_failed callback
|
68
|
-
def on_connect_failed
|
69
|
-
adapter.tcp_connection_failed
|
70
|
-
end
|
71
|
-
|
72
|
-
# Sends raw data through the socket
|
73
|
-
#
|
74
|
-
# param [String] Binary data
|
75
|
-
def send_raw(data)
|
76
|
-
# puts "Sending data"
|
77
|
-
# puts_data(data)
|
78
|
-
write(data)
|
79
|
-
end
|
80
|
-
|
81
|
-
protected
|
82
|
-
# Debugging routine
|
83
|
-
def puts_data(data)
|
84
|
-
puts " As string: #{data.inspect}"
|
85
|
-
puts " As byte array: #{data.bytes.to_a.inspect}"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# Cool.io socket for multiplexing et al.
|
92
|
-
#
|
93
|
-
# @private
|
94
|
-
attr_accessor :socket
|
95
|
-
|
96
|
-
# Hash with available callbacks
|
97
|
-
attr_accessor :callbacks
|
98
|
-
|
99
|
-
# Creates a socket and attaches it to cool.io default loop.
|
100
|
-
#
|
101
|
-
# Called from CoolioClient.connect
|
102
|
-
#
|
103
|
-
# @see AMQ::Client::Adapter::ClassMethods#connect
|
104
|
-
# @param [Hash] connection settings
|
105
|
-
# @api private
|
106
|
-
def establish_connection(settings)
|
107
|
-
@settings = Settings.configure(settings)
|
108
|
-
|
109
|
-
socket = Socket.connect(self, @settings[:host], @settings[:port])
|
110
|
-
socket.attach(Cool.io::Loop.default)
|
111
|
-
self.socket = socket
|
112
|
-
|
113
|
-
|
114
|
-
@on_tcp_connection_failure = @settings[:on_tcp_connection_failure] || Proc.new { |settings|
|
115
|
-
raise self.class.tcp_connection_failure_exception_class.new(settings)
|
116
|
-
}
|
117
|
-
@on_possible_authentication_failure = @settings[:on_possible_authentication_failure] || Proc.new { |settings|
|
118
|
-
raise self.class.authentication_failure_exception_class.new(settings)
|
119
|
-
}
|
120
|
-
|
121
|
-
@locale = @settings.fetch(:locale, "en_GB")
|
122
|
-
@client_properties = Settings.client_properties.merge(@settings.fetch(:client_properties, Hash.new))
|
123
|
-
|
124
|
-
socket
|
125
|
-
end
|
126
|
-
|
127
|
-
# Registers on_open callback
|
128
|
-
# @see #on_open
|
129
|
-
# @api private
|
130
|
-
def register_connection_callback(&block)
|
131
|
-
self.on_open(&block)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Performs basic initialization. Do not use this method directly, use
|
135
|
-
# CoolioClient.connect instead
|
136
|
-
#
|
137
|
-
# @see AMQ::Client::Adapter::ClassMethods#connect
|
138
|
-
# @api private
|
139
|
-
def initialize
|
140
|
-
# Be careful with default values for #ruby hashes: h = Hash.new(Array.new); h[:key] ||= 1
|
141
|
-
# won't assign anything to :key. MK.
|
142
|
-
@callbacks = Hash.new
|
143
|
-
|
144
|
-
self.logger = self.class.logger
|
145
|
-
|
146
|
-
@frames = Array.new
|
147
|
-
@channels = Hash.new
|
148
|
-
|
149
|
-
@mechanism = "PLAIN"
|
150
|
-
end
|
151
|
-
|
152
|
-
# Sets a callback for successful connection (after we receive open-ok)
|
153
|
-
#
|
154
|
-
# @api public
|
155
|
-
def on_open(&block)
|
156
|
-
define_callback :connect, &block
|
157
|
-
end
|
158
|
-
alias on_connection on_open
|
159
|
-
|
160
|
-
# Sets a callback for disconnection (as in client-side disconnection)
|
161
|
-
#
|
162
|
-
# @api public
|
163
|
-
def on_closed(&block)
|
164
|
-
define_callback :disconnect, &block
|
165
|
-
end
|
166
|
-
alias on_disconnection on_closed
|
167
|
-
|
168
|
-
# Sets a callback for tcp connection failure (as in can't make initial connection)
|
169
|
-
def on_tcp_connection_failure(&block)
|
170
|
-
define_callback :tcp_connection_failure, &block
|
171
|
-
end
|
172
|
-
|
173
|
-
|
174
|
-
# Called by AMQ::Client::Connection after we receive connection.open-ok.
|
175
|
-
#
|
176
|
-
# @api private
|
177
|
-
def connection_successful
|
178
|
-
@authenticating = false
|
179
|
-
opened!
|
180
|
-
|
181
|
-
exec_callback_yielding_self(:connect)
|
182
|
-
end
|
183
|
-
|
184
|
-
|
185
|
-
# Called by AMQ::Client::Connection after we receive connection.close-ok.
|
186
|
-
#
|
187
|
-
# @api private
|
188
|
-
def disconnection_successful
|
189
|
-
exec_callback_yielding_self(:disconnect)
|
190
|
-
close_connection
|
191
|
-
closed!
|
192
|
-
end
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
# Called when socket is connected but before handshake is done
|
197
|
-
#
|
198
|
-
# @api private
|
199
|
-
def socket_connected
|
200
|
-
post_init
|
201
|
-
end
|
202
|
-
|
203
|
-
# Called after socket is closed
|
204
|
-
#
|
205
|
-
# @api private
|
206
|
-
def socket_disconnected
|
207
|
-
end
|
208
|
-
|
209
|
-
alias close disconnect
|
210
|
-
|
211
|
-
|
212
|
-
self.handle(Protocol::Connection::Start) do |connection, frame|
|
213
|
-
connection.handle_start(frame.decode_payload)
|
214
|
-
end
|
215
|
-
|
216
|
-
self.handle(Protocol::Connection::Tune) do |connection, frame|
|
217
|
-
connection.handle_tune(frame.decode_payload)
|
218
|
-
|
219
|
-
connection.open(connection.vhost)
|
220
|
-
end
|
221
|
-
|
222
|
-
self.handle(Protocol::Connection::OpenOk) do |connection, frame|
|
223
|
-
connection.handle_open_ok(frame.decode_payload)
|
224
|
-
end
|
225
|
-
|
226
|
-
self.handle(Protocol::Connection::Close) do |connection, frame|
|
227
|
-
connection.handle_close(frame.decode_payload)
|
228
|
-
end
|
229
|
-
|
230
|
-
self.handle(Protocol::Connection::CloseOk) do |connection, frame|
|
231
|
-
connection.handle_close_ok(frame.decode_payload)
|
232
|
-
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
# Sends raw data through the socket
|
239
|
-
#
|
240
|
-
# @param [String] binary data
|
241
|
-
# @api private
|
242
|
-
def send_raw(data)
|
243
|
-
socket.send_raw data
|
244
|
-
end
|
245
|
-
|
246
|
-
|
247
|
-
# The story about the buffering is kinda similar to EventMachine,
|
248
|
-
# you keep receiving more than one frame in a single packet.
|
249
|
-
#
|
250
|
-
# @param [String] chunk with binary data received. It could be one frame,
|
251
|
-
# more than one frame or less than one frame.
|
252
|
-
# @api private
|
253
|
-
def receive_data(chunk)
|
254
|
-
@chunk_buffer << chunk
|
255
|
-
while frame = get_next_frame
|
256
|
-
receive_frame(AMQ::Client::Framing::String::Frame.decode(frame))
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
# Closes the socket.
|
261
|
-
#
|
262
|
-
# @api private
|
263
|
-
def close_connection
|
264
|
-
@socket.close
|
265
|
-
end
|
266
|
-
|
267
|
-
# Returns class used for tcp connection failures.
|
268
|
-
#
|
269
|
-
# @api private
|
270
|
-
def self.tcp_connection_failure_exception_class
|
271
|
-
AMQ::Client::TCPConnectionFailed
|
272
|
-
end # self.tcp_connection_failure_exception_class
|
273
|
-
|
274
|
-
protected
|
275
|
-
|
276
|
-
# @api private
|
277
|
-
def post_init
|
278
|
-
self.reset
|
279
|
-
self.handshake
|
280
|
-
end
|
281
|
-
|
282
|
-
# @api private
|
283
|
-
def reset
|
284
|
-
@chunk_buffer = ""
|
285
|
-
@frames = Array.new
|
286
|
-
end
|
287
|
-
end # CoolioClient
|
7
|
+
# backwards compatibility
|
8
|
+
# @private
|
9
|
+
CoolioClient = Async::CoolioClient
|
288
10
|
end # Client
|
289
11
|
end # AMQ
|
@@ -1,389 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require "eventmachine"
|
4
|
-
require "amq/client"
|
5
|
-
require "amq/client/framing/string/frame"
|
3
|
+
require "amq/client/async/adapters/eventmachine"
|
6
4
|
|
7
5
|
module AMQ
|
8
6
|
module Client
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# Behaviors
|
13
|
-
#
|
14
|
-
|
15
|
-
include AMQ::Client::Adapter
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
# API
|
20
|
-
#
|
21
|
-
|
22
|
-
# Initiates connection to AMQP broker. If callback is given, runs it when (and if) AMQP connection
|
23
|
-
# succeeds.
|
24
|
-
#
|
25
|
-
# @option settings [String] :host ("127.0.0.1") Hostname AMQ broker runs on.
|
26
|
-
# @option settings [String] :port (5672) Port AMQ broker listens on.
|
27
|
-
# @option settings [String] :vhost ("/") Virtual host to use.
|
28
|
-
# @option settings [String] :user ("guest") Username to use for authentication.
|
29
|
-
# @option settings [String] :pass ("guest") Password to use for authentication.
|
30
|
-
# @option settings [String] :ssl (false) Should be use TLS (SSL) for connection?
|
31
|
-
# @option settings [String] :timeout (nil) Connection timeout.
|
32
|
-
# @option settings [String] :logging (false) Turns logging on or off.
|
33
|
-
# @option settings [String] :broker (nil) Broker name (use if you intend to use broker-specific features).
|
34
|
-
# @option settings [Fixnum] :frame_max (131072) Maximum frame size to use. If broker cannot support frames this large, broker's maximum value will be used instead.
|
35
|
-
#
|
36
|
-
# @param [Hash] settings
|
37
|
-
def self.connect(settings = {}, &block)
|
38
|
-
@settings = Settings.configure(settings)
|
39
|
-
|
40
|
-
instance = EventMachine.connect(@settings[:host], @settings[:port], self, @settings)
|
41
|
-
instance.register_connection_callback(&block)
|
42
|
-
|
43
|
-
instance
|
44
|
-
end
|
45
|
-
|
46
|
-
# Reconnect after a period of wait.
|
47
|
-
#
|
48
|
-
# @param [Fixnum] period Period of time, in seconds, to wait before reconnection attempt.
|
49
|
-
# @param [Boolean] force If true, enforces immediate reconnection.
|
50
|
-
# @api public
|
51
|
-
def reconnect(force = false, period = 5)
|
52
|
-
if @reconnecting and not force
|
53
|
-
EventMachine::Timer.new(period) {
|
54
|
-
reconnect(true, period)
|
55
|
-
}
|
56
|
-
return
|
57
|
-
end
|
58
|
-
|
59
|
-
if !@reconnecting
|
60
|
-
@reconnecting = true
|
61
|
-
|
62
|
-
self.handle_connection_interruption
|
63
|
-
self.reset
|
64
|
-
end
|
65
|
-
|
66
|
-
EventMachine.reconnect(@settings[:host], @settings[:port], self)
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
# Defines a callback that will be executed when AMQP connection is considered open:
|
74
|
-
# client and broker has agreed on max channel identifier and maximum allowed frame
|
75
|
-
# size and authentication succeeds. You can define more than one callback.
|
76
|
-
#
|
77
|
-
# @see on_possible_authentication_failure
|
78
|
-
# @api public
|
79
|
-
def on_open(&block)
|
80
|
-
@connection_deferrable.callback(&block)
|
81
|
-
end # on_open(&block)
|
82
|
-
alias on_connection on_open
|
83
|
-
|
84
|
-
# Defines a callback that will be run when broker confirms connection termination
|
85
|
-
# (client receives connection.close-ok). You can define more than one callback.
|
86
|
-
#
|
87
|
-
# @api public
|
88
|
-
def on_closed(&block)
|
89
|
-
@disconnection_deferrable.callback(&block)
|
90
|
-
end # on_closed(&block)
|
91
|
-
alias on_disconnection on_closed
|
92
|
-
|
93
|
-
# Defines a callback that will be run when initial TCP connection fails.
|
94
|
-
# You can define only one callback.
|
95
|
-
#
|
96
|
-
# @api public
|
97
|
-
def on_tcp_connection_failure(&block)
|
98
|
-
@on_tcp_connection_failure = block
|
99
|
-
end
|
100
|
-
|
101
|
-
# Defines a callback that will be run when initial TCP connection fails.
|
102
|
-
# You can define only one callback.
|
103
|
-
#
|
104
|
-
# @api public
|
105
|
-
def on_tcp_connection_loss(&block)
|
106
|
-
@on_tcp_connection_loss = block
|
107
|
-
end
|
108
|
-
|
109
|
-
# Defines a callback that will be run when TCP connection is closed before authentication
|
110
|
-
# finishes. Usually this means authentication failure. You can define only one callback.
|
111
|
-
#
|
112
|
-
# @api public
|
113
|
-
def on_possible_authentication_failure(&block)
|
114
|
-
@on_possible_authentication_failure = block
|
115
|
-
end
|
116
|
-
|
117
|
-
# @see #on_open
|
118
|
-
# @private
|
119
|
-
def register_connection_callback(&block)
|
120
|
-
unless block.nil?
|
121
|
-
# delay calling block we were given till after we receive
|
122
|
-
# connection.open-ok. Connection will notify us when
|
123
|
-
# that happens.
|
124
|
-
self.on_open do
|
125
|
-
block.call(self)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
def initialize(*args)
|
134
|
-
super(*args)
|
135
|
-
|
136
|
-
self.logger = self.class.logger
|
137
|
-
|
138
|
-
@frames = Array.new
|
139
|
-
@channels = Hash.new
|
140
|
-
@callbacks = Hash.new
|
141
|
-
|
142
|
-
opening!
|
143
|
-
|
144
|
-
# track TCP connection state, used to detect initial TCP connection failures.
|
145
|
-
@tcp_connection_established = false
|
146
|
-
@tcp_connection_failed = false
|
147
|
-
@intentionally_closing_connection = false
|
148
|
-
|
149
|
-
# EventMachine::Connection's and Adapter's constructors arity
|
150
|
-
# make it easier to use *args. MK.
|
151
|
-
@settings = Settings.configure(args.first)
|
152
|
-
@on_tcp_connection_failure = @settings[:on_tcp_connection_failure] || Proc.new { |settings|
|
153
|
-
raise self.class.tcp_connection_failure_exception_class.new(settings)
|
154
|
-
}
|
155
|
-
@on_possible_authentication_failure = @settings[:on_possible_authentication_failure] || Proc.new { |settings|
|
156
|
-
raise self.class.authentication_failure_exception_class.new(settings)
|
157
|
-
}
|
158
|
-
|
159
|
-
@mechanism = "PLAIN"
|
160
|
-
@locale = @settings.fetch(:locale, "en_GB")
|
161
|
-
@client_properties = Settings.client_properties.merge(@settings.fetch(:client_properties, Hash.new))
|
162
|
-
|
163
|
-
self.reset
|
164
|
-
self.set_pending_connect_timeout((@settings[:timeout] || 3).to_f) unless defined?(JRUBY_VERSION)
|
165
|
-
|
166
|
-
if self.heartbeat_interval > 0
|
167
|
-
@last_server_heartbeat = Time.now
|
168
|
-
EventMachine.add_periodic_timer(self.heartbeat_interval, &method(:send_heartbeat))
|
169
|
-
end
|
170
|
-
end # initialize(*args)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
# For EventMachine adapter, this is a no-op.
|
175
|
-
# @api public
|
176
|
-
def establish_connection(settings)
|
177
|
-
# Unfortunately there doesn't seem to be any sane way
|
178
|
-
# how to get EventMachine connect to the instance level.
|
179
|
-
end
|
180
|
-
|
181
|
-
alias close disconnect
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
# Whether we are in authentication state (after TCP connection was estabilished
|
186
|
-
# but before broker authenticated us).
|
187
|
-
#
|
188
|
-
# @return [Boolean]
|
189
|
-
# @api public
|
190
|
-
def authenticating?
|
191
|
-
@authenticating
|
192
|
-
end # authenticating?
|
193
|
-
|
194
|
-
# IS TCP connection estabilished and currently active?
|
195
|
-
# @return [Boolean]
|
196
|
-
# @api public
|
197
|
-
def tcp_connection_established?
|
198
|
-
@tcp_connection_established
|
199
|
-
end # tcp_connection_established?
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
#
|
207
|
-
# Implementation
|
208
|
-
#
|
209
|
-
|
210
|
-
# Backwards compatibility with 0.7.0.a25. MK.
|
211
|
-
Deferrable = EventMachine::DefaultDeferrable
|
212
|
-
|
213
|
-
|
214
|
-
alias send_raw send_data
|
215
|
-
|
216
|
-
|
217
|
-
# EventMachine reactor callback. Is run when TCP connection is estabilished
|
218
|
-
# but before resumption of the network loop. Note that this includes cases
|
219
|
-
# when TCP connection has failed.
|
220
|
-
# @private
|
221
|
-
def post_init
|
222
|
-
reset
|
223
|
-
|
224
|
-
# note that upgrading to TLS in #connection_completed causes
|
225
|
-
# Erlang SSL app that RabbitMQ relies on to report
|
226
|
-
# error on TCP connection <0.1465.0>:{ssl_upgrade_error,"record overflow"}
|
227
|
-
# and close TCP connection down. Investigation of this issue is likely
|
228
|
-
# to take some time and to not be worth in as long as #post_init
|
229
|
-
# works fine. MK.
|
230
|
-
upgrade_to_tls_if_necessary
|
231
|
-
rescue Exception => error
|
232
|
-
raise error
|
233
|
-
end # post_init
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
# Called by EventMachine reactor once TCP connection is successfully estabilished.
|
238
|
-
# @private
|
239
|
-
def connection_completed
|
240
|
-
# we only can safely set this value here because EventMachine is a lovely piece of
|
241
|
-
# software that calls #post_init before #unbind even when TCP connection
|
242
|
-
# fails. MK.
|
243
|
-
@tcp_connection_established = true
|
244
|
-
# again, this is because #unbind is called in different situations
|
245
|
-
# and there is no easy way to tell initial connection failure
|
246
|
-
# from connection loss. Not in EventMachine 0.12.x, anyway. MK.
|
247
|
-
@had_successfull_connected_before = true
|
248
|
-
|
249
|
-
@reconnecting = false
|
250
|
-
|
251
|
-
self.handshake
|
252
|
-
end
|
253
|
-
|
254
|
-
# @private
|
255
|
-
def close_connection(*args)
|
256
|
-
@intentionally_closing_connection = true
|
257
|
-
|
258
|
-
super(*args)
|
259
|
-
end
|
260
|
-
|
261
|
-
# Called by EventMachine reactor when
|
262
|
-
#
|
263
|
-
# * We close TCP connection down
|
264
|
-
# * Our peer closes TCP connection down
|
265
|
-
# * There is a network connection issue
|
266
|
-
# * Initial TCP connection fails
|
267
|
-
# @private
|
268
|
-
def unbind(exception = nil)
|
269
|
-
if !@tcp_connection_established && !@had_successfull_connected_before && !@intentionally_closing_connection
|
270
|
-
@tcp_connection_failed = true
|
271
|
-
self.tcp_connection_failed
|
272
|
-
end
|
273
|
-
|
274
|
-
closing!
|
275
|
-
@tcp_connection_established = false
|
276
|
-
|
277
|
-
self.handle_connection_interruption
|
278
|
-
@disconnection_deferrable.succeed
|
279
|
-
|
280
|
-
closed!
|
281
|
-
|
282
|
-
|
283
|
-
self.tcp_connection_lost if !@intentionally_closing_connection && @had_successfull_connected_before
|
284
|
-
|
285
|
-
# since AMQP spec dictates that authentication failure is a protocol exception
|
286
|
-
# and protocol exceptions result in connection closure, check whether we are
|
287
|
-
# in the authentication stage. If so, it is likely to signal an authentication
|
288
|
-
# issue. Java client behaves the same way. MK.
|
289
|
-
if authenticating? && !@intentionally_closing_connection
|
290
|
-
@on_possible_authentication_failure.call(@settings) if @on_possible_authentication_failure
|
291
|
-
end
|
292
|
-
end # unbind
|
293
|
-
|
294
|
-
|
295
|
-
#
|
296
|
-
# EventMachine receives data in chunks, sometimes those chunks are smaller
|
297
|
-
# than the size of AMQP frame. That's why you need to add some kind of buffer.
|
298
|
-
#
|
299
|
-
# @private
|
300
|
-
def receive_data(chunk)
|
301
|
-
@chunk_buffer << chunk
|
302
|
-
while frame = get_next_frame
|
303
|
-
self.receive_frame(AMQ::Client::Framing::String::Frame.decode(frame))
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
|
308
|
-
# Called by AMQ::Client::Connection after we receive connection.open-ok.
|
309
|
-
# @api public
|
310
|
-
def connection_successful
|
311
|
-
@authenticating = false
|
312
|
-
opened!
|
313
|
-
|
314
|
-
@connection_deferrable.succeed
|
315
|
-
end # connection_successful
|
316
|
-
|
317
|
-
|
318
|
-
# Called by AMQ::Client::Connection after we receive connection.close-ok.
|
319
|
-
#
|
320
|
-
# @api public
|
321
|
-
def disconnection_successful
|
322
|
-
@disconnection_deferrable.succeed
|
323
|
-
|
324
|
-
# true for "after writing buffered data"
|
325
|
-
self.close_connection(true)
|
326
|
-
self.reset
|
327
|
-
closed!
|
328
|
-
end # disconnection_successful
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
self.handle(Protocol::Connection::Start) do |connection, frame|
|
335
|
-
connection.handle_start(frame.decode_payload)
|
336
|
-
end
|
337
|
-
|
338
|
-
self.handle(Protocol::Connection::Tune) do |connection, frame|
|
339
|
-
connection.handle_tune(frame.decode_payload)
|
340
|
-
|
341
|
-
connection.open(connection.vhost)
|
342
|
-
end
|
343
|
-
|
344
|
-
self.handle(Protocol::Connection::OpenOk) do |connection, frame|
|
345
|
-
connection.handle_open_ok(frame.decode_payload)
|
346
|
-
end
|
347
|
-
|
348
|
-
self.handle(Protocol::Connection::Close) do |connection, frame|
|
349
|
-
connection.handle_close(frame.decode_payload)
|
350
|
-
end
|
351
|
-
|
352
|
-
self.handle(Protocol::Connection::CloseOk) do |connection, frame|
|
353
|
-
connection.handle_close_ok(frame.decode_payload)
|
354
|
-
end
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
protected
|
360
|
-
|
361
|
-
|
362
|
-
def reset
|
363
|
-
@size = 0
|
364
|
-
@payload = ""
|
365
|
-
@frames = Array.new
|
366
|
-
|
367
|
-
@chunk_buffer = ""
|
368
|
-
@connection_deferrable = EventMachine::DefaultDeferrable.new
|
369
|
-
@disconnection_deferrable = EventMachine::DefaultDeferrable.new
|
370
|
-
|
371
|
-
# used to track down whether authentication succeeded. AMQP 0.9.1 dictates
|
372
|
-
# that on authentication failure broker must close TCP connection without sending
|
373
|
-
# any more data. This is why we need to explicitly track whether we are past
|
374
|
-
# authentication stage to signal possible authentication failures.
|
375
|
-
@authenticating = false
|
376
|
-
end
|
377
|
-
|
378
|
-
def upgrade_to_tls_if_necessary
|
379
|
-
tls_options = @settings[:ssl]
|
380
|
-
|
381
|
-
if tls_options.is_a?(Hash)
|
382
|
-
start_tls(tls_options)
|
383
|
-
elsif tls_options
|
384
|
-
start_tls
|
385
|
-
end
|
386
|
-
end # upgrade_to_tls_if_necessary
|
387
|
-
end # EventMachineClient
|
7
|
+
# backwards compatibility
|
8
|
+
# @private
|
9
|
+
EventMachineClient = Async::EventMachineClient
|
388
10
|
end # Client
|
389
11
|
end # AMQ
|