bunny 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bunny.gemspec +2 -2
- data/examples/simple_08.rb +1 -1
- data/examples/simple_09.rb +1 -1
- data/examples/simple_ack_08.rb +1 -1
- data/examples/simple_ack_09.rb +1 -1
- data/examples/simple_consumer_08.rb +15 -9
- data/examples/simple_consumer_09.rb +15 -9
- data/examples/simple_fanout_08.rb +1 -1
- data/examples/simple_fanout_09.rb +1 -1
- data/examples/simple_headers_08.rb +1 -1
- data/examples/simple_headers_09.rb +1 -1
- data/examples/simple_publisher_08.rb +2 -2
- data/examples/simple_topic_08.rb +1 -1
- data/examples/simple_topic_09.rb +1 -1
- data/lib/bunny.rb +1 -1
- data/lib/bunny/client08.rb +115 -51
- data/lib/bunny/client09.rb +117 -53
- data/lib/bunny/queue08.rb +19 -5
- data/lib/bunny/queue09.rb +19 -5
- data/lib/qrack/client.rb +2 -2
- data/spec/spec_08/bunny_spec.rb +23 -4
- data/spec/spec_08/exchange_spec.rb +31 -23
- data/spec/spec_08/queue_spec.rb +4 -4
- data/spec/spec_09/bunny_spec.rb +23 -4
- data/spec/spec_09/exchange_spec.rb +31 -23
- data/spec/spec_09/queue_spec.rb +4 -4
- metadata +2 -2
data/bunny.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = %q{bunny}
|
3
|
-
s.version = "0.5.
|
3
|
+
s.version = "0.5.2"
|
4
4
|
s.authors = ["Chris Duncan"]
|
5
|
-
s.date = %q{2009-08-
|
5
|
+
s.date = %q{2009-08-17}
|
6
6
|
s.description = %q{Another synchronous Ruby AMQP client}
|
7
7
|
s.email = %q{celldee@gmail.com}
|
8
8
|
s.rubyforge_project = %q{bunny-amqp}
|
data/examples/simple_08.rb
CHANGED
data/examples/simple_09.rb
CHANGED
data/examples/simple_ack_08.rb
CHANGED
data/examples/simple_ack_09.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# simple_consumer_08.rb
|
2
2
|
|
3
3
|
# N.B. To be used in conjunction with simple_publisher.rb
|
4
4
|
|
@@ -13,15 +13,18 @@
|
|
13
13
|
#
|
14
14
|
# Open up two console windows start this program in one of them by typing -
|
15
15
|
#
|
16
|
-
# ruby
|
16
|
+
# ruby simple_consumer_08.rb
|
17
17
|
#
|
18
18
|
# Then switch to the other console window and type -
|
19
19
|
#
|
20
|
-
# ruby
|
20
|
+
# ruby simple_publisher_08.rb
|
21
21
|
#
|
22
22
|
# A message will be printed out by the simple_consumer and it will wait for the next message
|
23
|
+
# until the timeout interval is reached.
|
23
24
|
#
|
24
|
-
# Run simple_publisher
|
25
|
+
# Run simple_publisher as many times as you like. When you want the program to stop just stop
|
26
|
+
# sending messages and the subscribe loop will timeout after 30 seconds, the program will
|
27
|
+
# unsubscribe from the queue and close the connection to the server.
|
25
28
|
|
26
29
|
$:.unshift File.dirname(__FILE__) + '/../lib'
|
27
30
|
|
@@ -45,11 +48,14 @@ q.bind(exch, :key => 'fred')
|
|
45
48
|
i = 1
|
46
49
|
|
47
50
|
# subscribe to queue
|
48
|
-
q.subscribe(:consumer_tag => 'testtag1') do |msg|
|
49
|
-
puts i.to_s
|
51
|
+
ret = q.subscribe(:consumer_tag => 'testtag1', :timeout => 30) do |msg|
|
52
|
+
puts "#{i.to_s}: #{msg}"
|
50
53
|
i+=1
|
51
|
-
q.unsubscribe(:consumer_tag => 'testtag1') if i == 5
|
52
54
|
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
if ret == :timed_out
|
57
|
+
puts '==== simple_consumer_08.rb timed out - closing down ===='
|
58
|
+
q.unsubscribe(:consumer_tag => 'testtag1')
|
59
|
+
# close the connection
|
60
|
+
b.stop
|
61
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# simple_consumer_09.rb
|
2
2
|
|
3
3
|
# N.B. To be used in conjunction with simple_publisher.rb
|
4
4
|
|
@@ -13,15 +13,18 @@
|
|
13
13
|
#
|
14
14
|
# Open up two console windows start this program in one of them by typing -
|
15
15
|
#
|
16
|
-
# ruby
|
16
|
+
# ruby simple_consumer_09.rb
|
17
17
|
#
|
18
18
|
# Then switch to the other console window and type -
|
19
19
|
#
|
20
|
-
# ruby
|
20
|
+
# ruby simple_publisher_09.rb
|
21
21
|
#
|
22
22
|
# A message will be printed out by the simple_consumer and it will wait for the next message
|
23
|
+
# until the timeout interval is reached.
|
23
24
|
#
|
24
|
-
# Run simple_publisher
|
25
|
+
# Run simple_publisher as many times as you like. When you want the program to stop just stop
|
26
|
+
# sending messages and the subscribe loop will timeout after 30 seconds, the program will
|
27
|
+
# unsubscribe from the queue and close the connection to the server.
|
25
28
|
|
26
29
|
$:.unshift File.dirname(__FILE__) + '/../lib'
|
27
30
|
|
@@ -45,11 +48,14 @@ q.bind(exch, :key => 'fred')
|
|
45
48
|
i = 1
|
46
49
|
|
47
50
|
# subscribe to queue
|
48
|
-
q.subscribe(:consumer_tag => 'testtag1') do |msg|
|
49
|
-
puts i.to_s
|
51
|
+
ret = q.subscribe(:consumer_tag => 'testtag1', :timeout => 30) do |msg|
|
52
|
+
puts "#{i.to_s}: #{msg}"
|
50
53
|
i+=1
|
51
|
-
q.unsubscribe(:consumer_tag => 'testtag1') if i == 5
|
52
54
|
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
if ret == :timed_out
|
57
|
+
puts '==== simple_consumer_09.rb timed out - closing down ===='
|
58
|
+
q.unsubscribe(:consumer_tag => 'testtag1')
|
59
|
+
# close the connection
|
60
|
+
b.stop
|
61
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# simple_publisher_08.rb
|
2
2
|
|
3
|
-
# N.B. To be used in conjunction with
|
3
|
+
# N.B. To be used in conjunction with simple_consumer_08.rb. See simple_consumer.rb for explanation.
|
4
4
|
|
5
5
|
# Assumes that target message broker/server has a user called 'guest' with a password 'guest'
|
6
6
|
# and that it is running on 'localhost'.
|
data/examples/simple_topic_08.rb
CHANGED
data/examples/simple_topic_09.rb
CHANGED
data/lib/bunny.rb
CHANGED
data/lib/bunny/client08.rb
CHANGED
@@ -34,6 +34,9 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
|
|
34
34
|
servers, the server may respond to a Connection::Open method with a Connection::Redirect. The insist
|
35
35
|
option, if set to _true_, tells the server that the client is insisting on a connection to the
|
36
36
|
specified server.
|
37
|
+
* <tt>:frame_max => maximum frame size in bytes (default = 131072)</tt>
|
38
|
+
* <tt>:channel_max => maximum number of channels (default = 0 no maximum)</tt>
|
39
|
+
* <tt>:heartbeat => number of seconds (default = 0 no heartbeat)</tt>
|
37
40
|
|
38
41
|
=end
|
39
42
|
|
@@ -50,10 +53,16 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
|
|
50
53
|
@status = :not_connected
|
51
54
|
@frame_max = opts[:frame_max] || 131072
|
52
55
|
@channel_max = opts[:channel_max] || 0
|
56
|
+
@heartbeat = opts[:heartbeat] || 0
|
53
57
|
@logger = nil
|
54
58
|
create_logger if @logging
|
59
|
+
@channels = []
|
55
60
|
# Create channel 0
|
56
61
|
@channel = Bunny::Channel.new(self, true)
|
62
|
+
@exchanges = {}
|
63
|
+
@queues = {}
|
64
|
+
@heartbeat_in = false
|
65
|
+
@connecting = false
|
57
66
|
end
|
58
67
|
|
59
68
|
=begin rdoc
|
@@ -91,18 +100,6 @@ Exchange
|
|
91
100
|
|
92
101
|
=== DESCRIPTION:
|
93
102
|
|
94
|
-
Returns hash of exchanges declared by Bunny.
|
95
|
-
|
96
|
-
=end
|
97
|
-
|
98
|
-
def exchanges
|
99
|
-
@exchanges ||= {}
|
100
|
-
end
|
101
|
-
|
102
|
-
=begin rdoc
|
103
|
-
|
104
|
-
=== DESCRIPTION:
|
105
|
-
|
106
103
|
Declares a queue to the broker/server. If the queue does not exist, a new one is created
|
107
104
|
using the arguments passed in. If the queue already exists, a reference to it is created, provided
|
108
105
|
that the arguments passed in do not conflict with the existing attributes of the queue. If an error
|
@@ -141,19 +138,16 @@ Queue
|
|
141
138
|
|
142
139
|
return queues[name] if queues.has_key?(name)
|
143
140
|
|
144
|
-
|
141
|
+
Bunny::Queue.new(self, name, opts)
|
145
142
|
end
|
146
|
-
|
147
|
-
=begin rdoc
|
148
|
-
|
149
|
-
=== DESCRIPTION:
|
150
|
-
|
151
|
-
Returns hash of queues declared by Bunny.
|
152
|
-
|
153
|
-
=end
|
154
143
|
|
155
|
-
def
|
156
|
-
|
144
|
+
def send_heartbeat
|
145
|
+
# Create a new heartbeat frame
|
146
|
+
hb = Qrack::Transport::Heartbeat.new('')
|
147
|
+
# Channel 0 must be used
|
148
|
+
switch_channel(0) if @channel.number > 0
|
149
|
+
# Send the heartbeat to server
|
150
|
+
send_frame(hb)
|
157
151
|
end
|
158
152
|
|
159
153
|
def send_frame(*args)
|
@@ -169,18 +163,72 @@ Returns hash of queues declared by Bunny.
|
|
169
163
|
nil
|
170
164
|
end
|
171
165
|
|
172
|
-
def next_frame
|
173
|
-
|
174
|
-
|
175
|
-
|
166
|
+
def next_frame(opts = {})
|
167
|
+
secs = opts[:timeout] || 0
|
168
|
+
|
169
|
+
begin
|
170
|
+
Timeout::timeout(secs) do
|
171
|
+
@frame = Qrack::Transport::Frame.parse(buffer)
|
172
|
+
end
|
173
|
+
rescue Timeout::Error
|
174
|
+
return :timed_out
|
175
|
+
end
|
176
|
+
|
177
|
+
@logger.info("received") { @frame } if @logging
|
178
|
+
|
179
|
+
raise Bunny::ConnectionError, 'No connection to server' if (@frame.nil? and !connecting?)
|
180
|
+
|
181
|
+
if @frame.is_a?(Qrack::Transport::Heartbeat)
|
182
|
+
@heartbeat_in = true
|
183
|
+
next_frame
|
184
|
+
end
|
185
|
+
|
186
|
+
@frame
|
176
187
|
end
|
177
188
|
|
178
189
|
def next_payload
|
179
|
-
frame = next_frame
|
190
|
+
frame = next_frame
|
180
191
|
frame.payload
|
181
192
|
end
|
182
193
|
|
183
194
|
alias next_method next_payload
|
195
|
+
|
196
|
+
=begin rdoc
|
197
|
+
|
198
|
+
=== DESCRIPTION:
|
199
|
+
|
200
|
+
Checks to see whether or not an undeliverable message has been returned as a result of a publish
|
201
|
+
with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
|
202
|
+
|
203
|
+
==== OPTIONS:
|
204
|
+
|
205
|
+
* <tt>:timeout => number of seconds (default = 0.1) - The method will wait for a return
|
206
|
+
message until this timeout interval is reached.
|
207
|
+
|
208
|
+
==== RETURNS:
|
209
|
+
|
210
|
+
<tt>:no_return</tt> if message was not returned before timeout .
|
211
|
+
<tt>{:header, :return_details, :payload}</tt> if message is returned. <tt>:return_details</tt> is
|
212
|
+
a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
|
213
|
+
|
214
|
+
=end
|
215
|
+
|
216
|
+
def returned_message(opts = {})
|
217
|
+
secs = opts[:timeout] || 0.1
|
218
|
+
frame = next_frame(:timeout => secs)
|
219
|
+
|
220
|
+
if frame.is_a?(Symbol)
|
221
|
+
return :no_return if frame == :timed_out
|
222
|
+
end
|
223
|
+
|
224
|
+
method = frame.payload
|
225
|
+
header = next_payload
|
226
|
+
msg = next_payload
|
227
|
+
raise Bunny::MessageError, 'unexpected length' if msg.length < header.size
|
228
|
+
|
229
|
+
# Return the message and related info
|
230
|
+
{:header => header, :payload => msg, :return_details => method.arguments}
|
231
|
+
end
|
184
232
|
|
185
233
|
=begin rdoc
|
186
234
|
|
@@ -197,12 +245,9 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
197
245
|
|
198
246
|
def close
|
199
247
|
# Close all active channels
|
200
|
-
channels.
|
248
|
+
channels.each do |c|
|
201
249
|
c.close if c.open?
|
202
250
|
end
|
203
|
-
|
204
|
-
# Set client channel to zero
|
205
|
-
self.channel = channels[0]
|
206
251
|
|
207
252
|
# Close connection to AMQP server
|
208
253
|
close_connection
|
@@ -235,6 +280,8 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
235
280
|
=end
|
236
281
|
|
237
282
|
def start_session
|
283
|
+
@connecting = true
|
284
|
+
|
238
285
|
loop do
|
239
286
|
# Create/get socket
|
240
287
|
socket
|
@@ -246,15 +293,17 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
246
293
|
break if open_connection == :ok
|
247
294
|
end
|
248
295
|
|
249
|
-
# Open
|
250
|
-
|
251
|
-
|
296
|
+
# Open another channel because channel zero is used for specific purposes
|
297
|
+
c = create_channel()
|
298
|
+
c.open
|
252
299
|
|
253
300
|
# Get access ticket
|
254
301
|
request_access
|
255
302
|
|
303
|
+
@connecting = false
|
304
|
+
|
256
305
|
# return status
|
257
|
-
status
|
306
|
+
@status = :connected
|
258
307
|
end
|
259
308
|
|
260
309
|
alias start start_session
|
@@ -263,7 +312,7 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
|
|
263
312
|
|
264
313
|
=== DESCRIPTION:
|
265
314
|
|
266
|
-
Asks the broker to redeliver all unacknowledged messages on a
|
315
|
+
Asks the broker to redeliver all unacknowledged messages on a specified channel. Zero or
|
267
316
|
more messages may be redelivered.
|
268
317
|
|
269
318
|
==== Options:
|
@@ -388,23 +437,36 @@ after a rollback.
|
|
388
437
|
@logging = bool
|
389
438
|
create_logger if @logging
|
390
439
|
end
|
391
|
-
|
392
|
-
def channels
|
393
|
-
@channels ||= {}
|
394
|
-
end
|
395
440
|
|
396
|
-
def
|
397
|
-
channels.
|
441
|
+
def create_channel
|
442
|
+
channels.each do |c|
|
398
443
|
return c if (!c.open? and c.number != 0)
|
399
444
|
end
|
400
445
|
# If no channel to re-use instantiate new one
|
401
446
|
Bunny::Channel.new(self)
|
402
447
|
end
|
403
448
|
|
449
|
+
def switch_channel(chann)
|
450
|
+
if (0...channels.size).include? chann
|
451
|
+
@channel = channels[chann]
|
452
|
+
chann
|
453
|
+
else
|
454
|
+
raise RuntimeError, "Invalid channel number - #{chann}"
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def connecting?
|
459
|
+
connecting
|
460
|
+
end
|
461
|
+
|
404
462
|
def init_connection
|
405
463
|
write(Qrack::Protocol::HEADER)
|
406
464
|
write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
|
407
|
-
|
465
|
+
|
466
|
+
frame = next_frame
|
467
|
+
if frame.nil? or !frame.payload.is_a?(Qrack::Protocol::Connection::Start)
|
468
|
+
raise Bunny::ProtocolError, 'Connection initiation failed'
|
469
|
+
end
|
408
470
|
end
|
409
471
|
|
410
472
|
def open_connection
|
@@ -417,12 +479,14 @@ after a rollback.
|
|
417
479
|
)
|
418
480
|
)
|
419
481
|
|
420
|
-
|
421
|
-
|
482
|
+
frame = next_frame
|
483
|
+
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if frame.nil?
|
484
|
+
|
485
|
+
method = frame.payload
|
422
486
|
|
423
487
|
if method.is_a?(Qrack::Protocol::Connection::Tune)
|
424
488
|
send_frame(
|
425
|
-
Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat =>
|
489
|
+
Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => @heartbeat)
|
426
490
|
)
|
427
491
|
end
|
428
492
|
|
@@ -444,6 +508,9 @@ after a rollback.
|
|
444
508
|
end
|
445
509
|
|
446
510
|
def close_connection
|
511
|
+
# Set client channel to zero
|
512
|
+
switch_channel(0)
|
513
|
+
|
447
514
|
send_frame(
|
448
515
|
Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
449
516
|
)
|
@@ -477,9 +544,7 @@ after a rollback.
|
|
477
544
|
def socket
|
478
545
|
return @socket if @socket and (@status == :connected) and not @socket.closed?
|
479
546
|
|
480
|
-
begin
|
481
|
-
@status = :not_connected
|
482
|
-
|
547
|
+
begin
|
483
548
|
# Attempt to connect.
|
484
549
|
@socket = timeout(CONNECT_TIMEOUT) do
|
485
550
|
TCPSocket.new(host, port)
|
@@ -488,7 +553,6 @@ after a rollback.
|
|
488
553
|
if Socket.constants.include? 'TCP_NODELAY'
|
489
554
|
@socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
490
555
|
end
|
491
|
-
@status = :connected
|
492
556
|
rescue => e
|
493
557
|
@status = :not_connected
|
494
558
|
raise Bunny::ServerDownError, e.message
|