bunny 0.4.4 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +21 -3
- data/bunny.gemspec +34 -20
- data/examples/{simple.rb → simple_08.rb} +0 -0
- data/examples/simple_09.rb +30 -0
- data/examples/{simple_ack.rb → simple_ack_08.rb} +0 -0
- data/examples/simple_ack_09.rb +33 -0
- data/examples/{simple_consumer.rb → simple_consumer_08.rb} +0 -0
- data/examples/simple_consumer_09.rb +55 -0
- data/examples/{simple_fanout.rb → simple_fanout_08.rb} +0 -0
- data/examples/simple_fanout_09.rb +39 -0
- data/examples/{simple_headers.rb → simple_headers_08.rb} +0 -0
- data/examples/simple_headers_09.rb +40 -0
- data/examples/{simple_publisher.rb → simple_publisher_08.rb} +0 -0
- data/examples/simple_publisher_09.rb +27 -0
- data/examples/{simple_topic.rb → simple_topic_08.rb} +0 -0
- data/examples/simple_topic_09.rb +59 -0
- data/lib/bunny.rb +19 -14
- data/lib/bunny/channel08.rb +38 -0
- data/lib/bunny/channel09.rb +38 -0
- data/lib/bunny/client08.rb +167 -74
- data/lib/bunny/{client091.rb → client09.rb} +195 -92
- data/lib/bunny/{exchange091.rb → exchange09.rb} +12 -11
- data/lib/bunny/queue08.rb +1 -0
- data/lib/bunny/{queue091.rb → queue09.rb} +38 -28
- data/lib/qrack/client.rb +7 -0
- data/lib/qrack/protocol/{protocol.rb → protocol08.rb} +1 -4
- data/lib/qrack/protocol/protocol09.rb +133 -0
- data/lib/qrack/protocol/{spec091.rb → spec09.rb} +5 -5
- data/lib/qrack/qrack08.rb +2 -10
- data/lib/qrack/qrack09.rb +20 -0
- data/lib/qrack/transport/{buffer.rb → buffer08.rb} +0 -0
- data/lib/qrack/transport/buffer09.rb +276 -0
- data/lib/qrack/transport/{frame091.rb → frame09.rb} +8 -8
- data/spec/{bunny_spec.rb → spec_08/bunny_spec.rb} +4 -4
- data/spec/{exchange_spec.rb → spec_08/exchange_spec.rb} +3 -10
- data/spec/{queue_spec.rb → spec_08/queue_spec.rb} +1 -1
- data/spec/spec_09/bunny_spec.rb +40 -0
- data/spec/spec_09/exchange_spec.rb +131 -0
- data/spec/spec_09/queue_spec.rb +106 -0
- metadata +38 -22
- data/lib/qrack/qrack091.rb +0 -28
@@ -0,0 +1,38 @@
|
|
1
|
+
module Bunny
|
2
|
+
class Channel
|
3
|
+
attr_accessor :number, :active
|
4
|
+
attr_reader :client
|
5
|
+
|
6
|
+
def initialize(client, zero = false)
|
7
|
+
@client = client
|
8
|
+
zero ? @number = 0 : @number = client.channels.size
|
9
|
+
@active = false
|
10
|
+
client.channels[@number] ||= self
|
11
|
+
end
|
12
|
+
|
13
|
+
def open
|
14
|
+
client.channel = self
|
15
|
+
client.send_frame(Qrack::Protocol::Channel::Open.new)
|
16
|
+
raise Bunny::ProtocolError, "Cannot open channel #{number}" unless client.next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
|
17
|
+
|
18
|
+
@active = true
|
19
|
+
:open_ok
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
client.channel = self
|
24
|
+
client.send_frame(
|
25
|
+
Qrack::Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
|
26
|
+
)
|
27
|
+
raise Bunny::ProtocolError, "Error closing channel #{number}" unless client.next_method.is_a?(Qrack::Protocol::Channel::CloseOk)
|
28
|
+
|
29
|
+
@active = false
|
30
|
+
:close_ok
|
31
|
+
end
|
32
|
+
|
33
|
+
def open?
|
34
|
+
active
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Bunny
|
2
|
+
class Channel09
|
3
|
+
attr_accessor :number, :active
|
4
|
+
attr_reader :client
|
5
|
+
|
6
|
+
def initialize(client, zero = false)
|
7
|
+
@client = client
|
8
|
+
zero ? @number = 0 : @number = client.channels.size
|
9
|
+
@active = false
|
10
|
+
client.channels[@number] ||= self
|
11
|
+
end
|
12
|
+
|
13
|
+
def open
|
14
|
+
client.channel = self
|
15
|
+
client.send_frame(Qrack::Protocol09::Channel::Open.new)
|
16
|
+
raise Bunny::ProtocolError, "Cannot open channel #{number}" unless client.next_method.is_a?(Qrack::Protocol09::Channel::OpenOk)
|
17
|
+
|
18
|
+
@active = true
|
19
|
+
:open_ok
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
client.channel = self
|
24
|
+
client.send_frame(
|
25
|
+
Qrack::Protocol09::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
|
26
|
+
)
|
27
|
+
raise Bunny::ProtocolError, "Error closing channel #{number}" unless client.next_method.is_a?(Qrack::Protocol09::Channel::CloseOk)
|
28
|
+
|
29
|
+
@active = false
|
30
|
+
:close_ok
|
31
|
+
end
|
32
|
+
|
33
|
+
def open?
|
34
|
+
active
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/bunny/client08.rb
CHANGED
@@ -9,11 +9,8 @@ The Client class provides the major Bunny API methods.
|
|
9
9
|
=end
|
10
10
|
|
11
11
|
class Client < Qrack::Client
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :status, :host, :vhost, :port, :logging, :spec
|
16
|
-
attr_accessor :channel, :logfile, :exchanges, :queues, :ticket
|
12
|
+
|
13
|
+
attr_accessor :ticket
|
17
14
|
|
18
15
|
=begin rdoc
|
19
16
|
|
@@ -41,7 +38,7 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
|
|
41
38
|
=end
|
42
39
|
|
43
40
|
def initialize(opts = {})
|
44
|
-
@spec =
|
41
|
+
@spec = '0-8'
|
45
42
|
@host = opts[:host] || 'localhost'
|
46
43
|
@port = opts[:port] || Qrack::Protocol::PORT
|
47
44
|
@user = opts[:user] || 'guest'
|
@@ -51,8 +48,12 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
|
|
51
48
|
@logging = opts[:logging] || false
|
52
49
|
@insist = opts[:insist]
|
53
50
|
@status = :not_connected
|
51
|
+
@frame_max = opts[:frame_max] || 131072
|
52
|
+
@channel_max = opts[:channel_max] || 0
|
54
53
|
@logger = nil
|
55
54
|
create_logger if @logging
|
55
|
+
# Create channel 0
|
56
|
+
@channel = Bunny::Channel.new(self, true)
|
56
57
|
end
|
57
58
|
|
58
59
|
=begin rdoc
|
@@ -60,9 +61,8 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
|
|
60
61
|
=== DESCRIPTION:
|
61
62
|
|
62
63
|
Declares an exchange to the broker/server. If the exchange does not exist, a new one is created
|
63
|
-
using the arguments passed in. If the exchange already exists,
|
64
|
-
|
65
|
-
occurs a _Bunny_::_ProtocolError_ is raised.
|
64
|
+
using the arguments passed in. If the exchange already exists, the existing object is returned.
|
65
|
+
If an error occurs a _Bunny_::_ProtocolError_ is raised.
|
66
66
|
|
67
67
|
==== OPTIONS:
|
68
68
|
|
@@ -83,7 +83,8 @@ Exchange
|
|
83
83
|
=end
|
84
84
|
|
85
85
|
def exchange(name, opts = {})
|
86
|
-
exchanges[name]
|
86
|
+
return exchanges[name] if exchanges.has_key?(name)
|
87
|
+
Bunny::Exchange.new(self, name, opts)
|
87
88
|
end
|
88
89
|
|
89
90
|
=begin rdoc
|
@@ -141,7 +142,6 @@ Queue
|
|
141
142
|
return queues[name] if queues.has_key?(name)
|
142
143
|
|
143
144
|
queue = Bunny::Queue.new(self, name, opts)
|
144
|
-
queues[queue.name] = queue
|
145
145
|
end
|
146
146
|
|
147
147
|
=begin rdoc
|
@@ -159,12 +159,13 @@ Returns hash of queues declared by Bunny.
|
|
159
159
|
def send_frame(*args)
|
160
160
|
args.each do |data|
|
161
161
|
data.ticket = ticket if ticket and data.respond_to?(:ticket=)
|
162
|
-
data = data.to_frame(channel) unless data.is_a?(Qrack::Transport::Frame)
|
163
|
-
data.channel = channel
|
162
|
+
data = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport::Frame)
|
163
|
+
data.channel = channel.number
|
164
164
|
|
165
165
|
@logger.info("send") { data } if @logging
|
166
166
|
write(data.to_s)
|
167
167
|
end
|
168
|
+
|
168
169
|
nil
|
169
170
|
end
|
170
171
|
|
@@ -174,15 +175,13 @@ Returns hash of queues declared by Bunny.
|
|
174
175
|
frame
|
175
176
|
end
|
176
177
|
|
177
|
-
def next_method
|
178
|
-
next_payload
|
179
|
-
end
|
180
|
-
|
181
178
|
def next_payload
|
182
179
|
frame = next_frame
|
183
|
-
|
180
|
+
frame.payload
|
184
181
|
end
|
185
182
|
|
183
|
+
alias next_method next_payload
|
184
|
+
|
186
185
|
=begin rdoc
|
187
186
|
|
188
187
|
=== DESCRIPTION:
|
@@ -197,17 +196,18 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
197
196
|
=end
|
198
197
|
|
199
198
|
def close
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
199
|
+
# Close all active channels
|
200
|
+
channels.each_value do |c|
|
201
|
+
c.close if c.open?
|
202
|
+
end
|
203
|
+
|
204
|
+
# Set client channel to zero
|
205
|
+
self.channel = channels[0]
|
204
206
|
|
205
|
-
|
206
|
-
|
207
|
-
Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
208
|
-
)
|
209
|
-
raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
|
207
|
+
# Close connection to AMQP server
|
208
|
+
close_connection
|
210
209
|
|
210
|
+
# Close TCP Socket
|
211
211
|
close_socket
|
212
212
|
end
|
213
213
|
|
@@ -239,56 +239,19 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
239
239
|
# Create/get socket
|
240
240
|
socket
|
241
241
|
|
242
|
-
|
243
|
-
|
244
|
-
write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
|
245
|
-
raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
|
242
|
+
# Initiate connection
|
243
|
+
init_connection
|
246
244
|
|
247
|
-
|
248
|
-
|
249
|
-
{:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
|
250
|
-
'AMQPLAIN',
|
251
|
-
{:LOGIN => @user, :PASSWORD => @pass},
|
252
|
-
'en_US'
|
253
|
-
)
|
254
|
-
)
|
255
|
-
|
256
|
-
method = next_method
|
257
|
-
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
258
|
-
|
259
|
-
if method.is_a?(Qrack::Protocol::Connection::Tune)
|
260
|
-
send_frame(
|
261
|
-
Qrack::Protocol::Connection::TuneOk.new( :channel_max => 0, :frame_max => 131072, :heartbeat => 0)
|
262
|
-
)
|
263
|
-
end
|
264
|
-
|
265
|
-
send_frame(
|
266
|
-
Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
|
267
|
-
)
|
268
|
-
|
269
|
-
case method = next_method
|
270
|
-
when Qrack::Protocol::Connection::OpenOk
|
271
|
-
break
|
272
|
-
when Qrack::Protocol::Connection::Redirect
|
273
|
-
raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
|
274
|
-
|
275
|
-
@host, @port = method.host.split(':')
|
276
|
-
close_socket
|
277
|
-
else
|
278
|
-
raise Bunny::ProtocolError, 'Cannot open connection'
|
279
|
-
end
|
245
|
+
# Open connection
|
246
|
+
break if open_connection == :ok
|
280
247
|
end
|
281
248
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
)
|
289
|
-
method = next_method
|
290
|
-
raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
|
291
|
-
self.ticket = method.ticket
|
249
|
+
# Open a channel
|
250
|
+
self.channel = get_channel
|
251
|
+
channel.open
|
252
|
+
|
253
|
+
# Get access ticket
|
254
|
+
request_access
|
292
255
|
|
293
256
|
# return status
|
294
257
|
status
|
@@ -360,11 +323,141 @@ true, they are applied to the entire connection.
|
|
360
323
|
# return confirmation
|
361
324
|
:qos_ok
|
362
325
|
end
|
326
|
+
|
327
|
+
=begin rdoc
|
328
|
+
|
329
|
+
=== DESCRIPTION:
|
330
|
+
This method sets the channel to use standard transactions. The
|
331
|
+
client must use this method at least once on a channel before
|
332
|
+
using the Commit or Rollback methods.
|
333
|
+
|
334
|
+
=end
|
335
|
+
|
336
|
+
def tx_select
|
337
|
+
send_frame(Qrack::Protocol::Tx::Select.new())
|
338
|
+
|
339
|
+
raise Bunny::ProtocolError,
|
340
|
+
"Error initiating transactions for current channel" unless
|
341
|
+
next_method.is_a?(Qrack::Protocol::Tx::SelectOk)
|
342
|
+
|
343
|
+
# return confirmation
|
344
|
+
:select_ok
|
345
|
+
end
|
346
|
+
|
347
|
+
=begin rdoc
|
348
|
+
|
349
|
+
=== DESCRIPTION:
|
350
|
+
This method commits all messages published and acknowledged in
|
351
|
+
the current transaction. A new transaction starts immediately
|
352
|
+
after a commit.
|
353
|
+
|
354
|
+
=end
|
355
|
+
|
356
|
+
def tx_commit
|
357
|
+
send_frame(Qrack::Protocol::Tx::Commit.new())
|
358
|
+
|
359
|
+
raise Bunny::ProtocolError,
|
360
|
+
"Error commiting transaction" unless
|
361
|
+
next_method.is_a?(Qrack::Protocol::Tx::CommitOk)
|
362
|
+
|
363
|
+
# return confirmation
|
364
|
+
:commit_ok
|
365
|
+
end
|
366
|
+
|
367
|
+
=begin rdoc
|
368
|
+
|
369
|
+
=== DESCRIPTION:
|
370
|
+
This method abandons all messages published and acknowledged in
|
371
|
+
the current transaction. A new transaction starts immediately
|
372
|
+
after a rollback.
|
373
|
+
|
374
|
+
=end
|
375
|
+
|
376
|
+
def tx_rollback
|
377
|
+
send_frame(Qrack::Protocol::Tx::Rollback.new())
|
378
|
+
|
379
|
+
raise Bunny::ProtocolError,
|
380
|
+
"Error rolling back transaction" unless
|
381
|
+
next_method.is_a?(Qrack::Protocol::Tx::RollbackOk)
|
382
|
+
|
383
|
+
# return confirmation
|
384
|
+
:rollback_ok
|
385
|
+
end
|
363
386
|
|
364
387
|
def logging=(bool)
|
365
388
|
@logging = bool
|
366
389
|
create_logger if @logging
|
367
390
|
end
|
391
|
+
|
392
|
+
def channels
|
393
|
+
@channels ||= {}
|
394
|
+
end
|
395
|
+
|
396
|
+
def get_channel
|
397
|
+
channels.each_value do |c|
|
398
|
+
return c if (!c.open? and c.number != 0)
|
399
|
+
end
|
400
|
+
# If no channel to re-use instantiate new one
|
401
|
+
Bunny::Channel.new(self)
|
402
|
+
end
|
403
|
+
|
404
|
+
def init_connection
|
405
|
+
write(Qrack::Protocol::HEADER)
|
406
|
+
write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
|
407
|
+
raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
|
408
|
+
end
|
409
|
+
|
410
|
+
def open_connection
|
411
|
+
send_frame(
|
412
|
+
Qrack::Protocol::Connection::StartOk.new(
|
413
|
+
{:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
|
414
|
+
'AMQPLAIN',
|
415
|
+
{:LOGIN => @user, :PASSWORD => @pass},
|
416
|
+
'en_US'
|
417
|
+
)
|
418
|
+
)
|
419
|
+
|
420
|
+
method = next_method
|
421
|
+
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
422
|
+
|
423
|
+
if method.is_a?(Qrack::Protocol::Connection::Tune)
|
424
|
+
send_frame(
|
425
|
+
Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => 0)
|
426
|
+
)
|
427
|
+
end
|
428
|
+
|
429
|
+
send_frame(
|
430
|
+
Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
|
431
|
+
)
|
432
|
+
|
433
|
+
case method = next_method
|
434
|
+
when Qrack::Protocol::Connection::OpenOk
|
435
|
+
return :ok
|
436
|
+
when Qrack::Protocol::Connection::Redirect
|
437
|
+
raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
|
438
|
+
|
439
|
+
@host, @port = method.host.split(':')
|
440
|
+
close_socket
|
441
|
+
else
|
442
|
+
raise Bunny::ProtocolError, 'Cannot open connection'
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
def close_connection
|
447
|
+
send_frame(
|
448
|
+
Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
449
|
+
)
|
450
|
+
raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
|
451
|
+
end
|
452
|
+
|
453
|
+
def request_access
|
454
|
+
send_frame(
|
455
|
+
Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
|
456
|
+
)
|
457
|
+
method = next_method
|
458
|
+
raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
|
459
|
+
self.ticket = method.ticket
|
460
|
+
end
|
368
461
|
|
369
462
|
private
|
370
463
|
|
@@ -8,12 +8,7 @@ The Client class provides the major Bunny API methods.
|
|
8
8
|
|
9
9
|
=end
|
10
10
|
|
11
|
-
class
|
12
|
-
CONNECT_TIMEOUT = 1.0
|
13
|
-
RETRY_DELAY = 10.0
|
14
|
-
|
15
|
-
attr_reader :status, :host, :vhost, :port, :logging, :spec
|
16
|
-
attr_accessor :channel, :logfile, :exchanges, :queues, :ticket
|
11
|
+
class Client09 < Qrack::Client
|
17
12
|
|
18
13
|
=begin rdoc
|
19
14
|
|
@@ -33,26 +28,25 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
|
|
33
28
|
* <tt>:logging => true or false (_default_)</tt> - If set to _true_, session information is sent
|
34
29
|
to STDOUT if <tt>:logfile</tt> has not been specified. Otherwise, session information is written to
|
35
30
|
<tt>:logfile</tt>.
|
36
|
-
* <tt>:insist => true or false (_default_)</tt> - In a configuration with multiple load-sharing
|
37
|
-
servers, the server may respond to a Connection::Open method with a Connection::Redirect. The insist
|
38
|
-
option, if set to _true_, tells the server that the client is insisting on a connection to the
|
39
|
-
specified server.
|
40
31
|
|
41
32
|
=end
|
42
33
|
|
43
34
|
def initialize(opts = {})
|
44
|
-
@spec =
|
35
|
+
@spec = '0-9-1'
|
45
36
|
@host = opts[:host] || 'localhost'
|
46
|
-
@port = opts[:port] || Qrack::
|
37
|
+
@port = opts[:port] || Qrack::Protocol09::PORT
|
47
38
|
@user = opts[:user] || 'guest'
|
48
39
|
@pass = opts[:pass] || 'guest'
|
49
40
|
@vhost = opts[:vhost] || '/'
|
41
|
+
@frame_max = opts[:frame_max] || 131072
|
42
|
+
@channel_max = opts[:channel_max] || 5
|
50
43
|
@logfile = opts[:logfile] || nil
|
51
44
|
@logging = opts[:logging] || false
|
52
|
-
@insist = opts[:insist]
|
53
45
|
@status = :not_connected
|
54
46
|
@logger = nil
|
55
47
|
create_logger if @logging
|
48
|
+
# Create channel 0
|
49
|
+
@channel = Bunny::Channel09.new(self, true)
|
56
50
|
end
|
57
51
|
|
58
52
|
=begin rdoc
|
@@ -83,7 +77,8 @@ Exchange
|
|
83
77
|
=end
|
84
78
|
|
85
79
|
def exchange(name, opts = {})
|
86
|
-
exchanges[name]
|
80
|
+
return exchanges[name] if exchanges.has_key?(name)
|
81
|
+
exchanges[name] ||= Bunny::Exchange09.new(self, name, opts)
|
87
82
|
end
|
88
83
|
|
89
84
|
=begin rdoc
|
@@ -140,8 +135,7 @@ Queue
|
|
140
135
|
|
141
136
|
return queues[name] if queues.has_key?(name)
|
142
137
|
|
143
|
-
queue = Bunny::
|
144
|
-
queues[queue.name] = queue
|
138
|
+
queue = Bunny::Queue09.new(self, name, opts)
|
145
139
|
end
|
146
140
|
|
147
141
|
=begin rdoc
|
@@ -158,9 +152,8 @@ Returns hash of queues declared by Bunny.
|
|
158
152
|
|
159
153
|
def send_frame(*args)
|
160
154
|
args.each do |data|
|
161
|
-
data
|
162
|
-
data
|
163
|
-
data.channel = channel
|
155
|
+
data = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport09::Frame)
|
156
|
+
data.channel = channel.number
|
164
157
|
|
165
158
|
@logger.info("send") { data } if @logging
|
166
159
|
write(data.to_s)
|
@@ -169,20 +162,18 @@ Returns hash of queues declared by Bunny.
|
|
169
162
|
end
|
170
163
|
|
171
164
|
def next_frame
|
172
|
-
frame = Qrack::
|
165
|
+
frame = Qrack::Transport09::Frame.parse(buffer)
|
173
166
|
@logger.info("received") { frame } if @logging
|
174
167
|
frame
|
175
168
|
end
|
176
169
|
|
177
|
-
def next_method
|
178
|
-
next_payload
|
179
|
-
end
|
180
|
-
|
181
170
|
def next_payload
|
182
171
|
frame = next_frame
|
183
|
-
|
172
|
+
frame.payload
|
184
173
|
end
|
185
174
|
|
175
|
+
alias next_method next_payload
|
176
|
+
|
186
177
|
=begin rdoc
|
187
178
|
|
188
179
|
=== DESCRIPTION:
|
@@ -197,17 +188,18 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
197
188
|
=end
|
198
189
|
|
199
190
|
def close
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
191
|
+
# Close all active channels
|
192
|
+
channels.each_value do |c|
|
193
|
+
c.close if c.open?
|
194
|
+
end
|
195
|
+
|
196
|
+
# Set client channel to zero
|
197
|
+
self.channel = channels[0]
|
198
|
+
|
199
|
+
# Close connection to AMQP server
|
200
|
+
close_connection
|
201
|
+
|
202
|
+
# Close TCP socket
|
211
203
|
close_socket
|
212
204
|
end
|
213
205
|
|
@@ -235,60 +227,18 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
235
227
|
=end
|
236
228
|
|
237
229
|
def start_session
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
'AMQPLAIN',
|
251
|
-
{:LOGIN => @user, :PASSWORD => @pass},
|
252
|
-
'en_US'
|
253
|
-
)
|
254
|
-
)
|
255
|
-
|
256
|
-
method = next_method
|
257
|
-
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
258
|
-
|
259
|
-
if method.is_a?(Qrack::Protocol::Connection::Tune)
|
260
|
-
send_frame(
|
261
|
-
Qrack::Protocol::Connection::TuneOk.new( :channel_max => 0, :frame_max => 131072, :heartbeat => 0)
|
262
|
-
)
|
263
|
-
end
|
264
|
-
|
265
|
-
send_frame(
|
266
|
-
Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
|
267
|
-
)
|
268
|
-
|
269
|
-
case method = next_method
|
270
|
-
when Qrack::Protocol::Connection::OpenOk
|
271
|
-
break
|
272
|
-
when Qrack::Protocol::Connection::Redirect
|
273
|
-
raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
|
274
|
-
|
275
|
-
@host, @port = method.host.split(':')
|
276
|
-
close_socket
|
277
|
-
else
|
278
|
-
raise Bunny::ProtocolError, 'Cannot open connection'
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
@channel = 1
|
283
|
-
send_frame(Qrack::Protocol::Channel::Open.new)
|
284
|
-
raise Bunny::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
|
285
|
-
|
286
|
-
send_frame(
|
287
|
-
Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
|
288
|
-
)
|
289
|
-
method = next_method
|
290
|
-
raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
|
291
|
-
self.ticket = method.ticket
|
230
|
+
# Create/get socket
|
231
|
+
socket
|
232
|
+
|
233
|
+
# Initiate connection
|
234
|
+
init_connection
|
235
|
+
|
236
|
+
# Open connection
|
237
|
+
open_connection
|
238
|
+
|
239
|
+
# Open a channel
|
240
|
+
self.channel = get_channel
|
241
|
+
channel.open
|
292
242
|
|
293
243
|
# return status
|
294
244
|
status
|
@@ -314,20 +264,173 @@ the message, potentially then delivering it to an alternative subscriber.
|
|
314
264
|
def recover(opts = {})
|
315
265
|
|
316
266
|
send_frame(
|
317
|
-
Qrack::
|
267
|
+
Qrack::Protocol09::Basic::Recover.new({ :requeue => false }.merge(opts))
|
318
268
|
)
|
319
269
|
|
320
270
|
end
|
321
271
|
|
272
|
+
=begin rdoc
|
273
|
+
|
274
|
+
=== DESCRIPTION:
|
275
|
+
|
276
|
+
Requests a specific quality of service. The QoS can be specified for the current channel
|
277
|
+
or for all channels on the connection. The particular properties and semantics of a QoS
|
278
|
+
method always depend on the content class semantics. Though the QoS method could in principle
|
279
|
+
apply to both peers, it is currently meaningful only for the server.
|
280
|
+
|
281
|
+
==== Options:
|
282
|
+
|
283
|
+
* <tt>:prefetch_size => size in no. of octets (default = 0)</tt> - The client can request that
|
284
|
+
messages be sent in advance so that when the client finishes processing a message, the following
|
285
|
+
message is already held locally, rather than needing to be sent down the channel. Prefetching gives
|
286
|
+
a performance improvement. This field specifies the prefetch window size in octets. The server
|
287
|
+
will send a message in advance if it is equal to or smaller in size than the available prefetch
|
288
|
+
size (and also falls into other prefetch limits). May be set to zero, meaning "no specific limit",
|
289
|
+
although other prefetch limits may still apply. The prefetch-size is ignored if the no-ack option
|
290
|
+
is set.
|
291
|
+
* <tt>:prefetch_count => no. messages (default = 1)</tt> - Specifies a prefetch window in terms
|
292
|
+
of whole messages. This field may be used in combination with the prefetch-size field; a message
|
293
|
+
will only be sent in advance if both prefetch windows (and those at the channel and connection level)
|
294
|
+
allow it. The prefetch-count is ignored if the no-ack option is set.
|
295
|
+
* <tt>:global => true or false (_default_)</tt> - By default the QoS settings apply to the current channel only. If set to
|
296
|
+
true, they are applied to the entire connection.
|
297
|
+
|
298
|
+
=end
|
299
|
+
|
300
|
+
def qos(opts = {})
|
301
|
+
|
302
|
+
send_frame(
|
303
|
+
Qrack::Protocol09::Basic::Qos.new({ :prefetch_size => 0, :prefetch_count => 1, :global => false }.merge(opts))
|
304
|
+
)
|
305
|
+
|
306
|
+
raise Bunny::ProtocolError,
|
307
|
+
"Error specifying Quality of Service" unless
|
308
|
+
next_method.is_a?(Qrack::Protocol09::Basic::QosOk)
|
309
|
+
|
310
|
+
# return confirmation
|
311
|
+
:qos_ok
|
312
|
+
end
|
313
|
+
|
314
|
+
=begin rdoc
|
315
|
+
|
316
|
+
=== DESCRIPTION:
|
317
|
+
This method sets the channel to use standard transactions. The
|
318
|
+
client must use this method at least once on a channel before
|
319
|
+
using the Commit or Rollback methods.
|
320
|
+
|
321
|
+
=end
|
322
|
+
|
323
|
+
def tx_select
|
324
|
+
send_frame(Qrack::Protocol09::Tx::Select.new())
|
325
|
+
|
326
|
+
raise Bunny::ProtocolError,
|
327
|
+
"Error initiating transactions for current channel" unless
|
328
|
+
next_method.is_a?(Qrack::Protocol09::Tx::SelectOk)
|
329
|
+
|
330
|
+
# return confirmation
|
331
|
+
:select_ok
|
332
|
+
end
|
333
|
+
|
334
|
+
=begin rdoc
|
335
|
+
|
336
|
+
=== DESCRIPTION:
|
337
|
+
This method commits all messages published and acknowledged in
|
338
|
+
the current transaction. A new transaction starts immediately
|
339
|
+
after a commit.
|
340
|
+
|
341
|
+
=end
|
342
|
+
|
343
|
+
def tx_commit
|
344
|
+
send_frame(Qrack::Protocol09::Tx::Commit.new())
|
345
|
+
|
346
|
+
raise Bunny::ProtocolError,
|
347
|
+
"Error commiting transaction" unless
|
348
|
+
next_method.is_a?(Qrack::Protocol09::Tx::CommitOk)
|
349
|
+
|
350
|
+
# return confirmation
|
351
|
+
:commit_ok
|
352
|
+
end
|
353
|
+
|
354
|
+
=begin rdoc
|
355
|
+
|
356
|
+
=== DESCRIPTION:
|
357
|
+
This method abandons all messages published and acknowledged in
|
358
|
+
the current transaction. A new transaction starts immediately
|
359
|
+
after a rollback.
|
360
|
+
|
361
|
+
=end
|
362
|
+
|
363
|
+
def tx_rollback
|
364
|
+
send_frame(Qrack::Protocol09::Tx::Rollback.new())
|
365
|
+
|
366
|
+
raise Bunny::ProtocolError,
|
367
|
+
"Error rolling back transaction" unless
|
368
|
+
next_method.is_a?(Qrack::Protocol09::Tx::RollbackOk)
|
369
|
+
|
370
|
+
# return confirmation
|
371
|
+
:rollback_ok
|
372
|
+
end
|
373
|
+
|
322
374
|
def logging=(bool)
|
323
375
|
@logging = bool
|
324
376
|
create_logger if @logging
|
325
377
|
end
|
378
|
+
|
379
|
+
def channels
|
380
|
+
@channels ||= {}
|
381
|
+
end
|
382
|
+
|
383
|
+
def get_channel
|
384
|
+
channels.each_value do |c|
|
385
|
+
return c if (!c.open? and c.number != 0)
|
386
|
+
end
|
387
|
+
# If no channel to re-use instantiate new one
|
388
|
+
Bunny::Channel09.new(self)
|
389
|
+
end
|
390
|
+
|
391
|
+
def init_connection
|
392
|
+
write(Qrack::Protocol09::HEADER)
|
393
|
+
write([0, Qrack::Protocol09::VERSION_MAJOR, Qrack::Protocol09::VERSION_MINOR, Qrack::Protocol09::REVISION].pack('C4'))
|
394
|
+
raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol09::Connection::Start)
|
395
|
+
end
|
396
|
+
|
397
|
+
def open_connection
|
398
|
+
send_frame(
|
399
|
+
Qrack::Protocol09::Connection::StartOk.new(
|
400
|
+
:client_properties => {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
|
401
|
+
:mechanism => 'PLAIN',
|
402
|
+
:response => "\0" + @user + "\0" + @pass,
|
403
|
+
:locale => 'en_US'
|
404
|
+
)
|
405
|
+
)
|
406
|
+
|
407
|
+
method = next_method
|
408
|
+
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
409
|
+
|
410
|
+
if method.is_a?(Qrack::Protocol09::Connection::Tune)
|
411
|
+
send_frame(
|
412
|
+
Qrack::Protocol09::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => 0)
|
413
|
+
)
|
414
|
+
end
|
415
|
+
|
416
|
+
send_frame(
|
417
|
+
Qrack::Protocol09::Connection::Open.new(:virtual_host => @vhost, :reserved_1 => 0, :reserved_2 => false)
|
418
|
+
)
|
419
|
+
|
420
|
+
raise Bunny::ProtocolError, 'Cannot open connection' unless next_method.is_a?(Qrack::Protocol09::Connection::OpenOk)
|
421
|
+
end
|
422
|
+
|
423
|
+
def close_connection
|
424
|
+
send_frame(
|
425
|
+
Qrack::Protocol09::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
426
|
+
)
|
427
|
+
raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol09::Connection::CloseOk)
|
428
|
+
end
|
326
429
|
|
327
430
|
private
|
328
431
|
|
329
432
|
def buffer
|
330
|
-
@buffer ||= Qrack::
|
433
|
+
@buffer ||= Qrack::Transport09::Buffer.new(self)
|
331
434
|
end
|
332
435
|
|
333
436
|
def send_command(cmd, *args)
|