bunny 0.4.4 → 0.5.1
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.
- 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)
|