bunny 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +15 -8
- data/examples/simple_consumer.rb +24 -5
- data/examples/{fanout.rb → simple_fanout.rb} +1 -6
- data/examples/simple_publisher.rb +1 -7
- data/examples/simple_topic.rb +59 -0
- data/lib/{amqp.rb → api_messages.rb} +1 -5
- data/lib/bunny.rb +21 -8
- data/lib/{amqp → bunny}/client.rb +16 -16
- data/lib/bunny/exchange.rb +16 -8
- data/lib/bunny/header.rb +1 -3
- data/lib/bunny/queue.rb +29 -20
- data/lib/{amqp → engineroom}/buffer.rb +6 -6
- data/lib/{amqp → engineroom}/frame.rb +4 -3
- data/lib/engineroom/protocol.rb +156 -0
- data/lib/engineroom/spec.rb +830 -0
- data/protocol/amqp-0.8.json +1 -1
- data/protocol/codegen.rb +83 -85
- data/spec/exchange_spec.rb +44 -2
- data/spec/queue_spec.rb +1 -1
- metadata +11 -12
- data/lib/amqp/protocol.rb +0 -158
- data/lib/amqp/spec.rb +0 -832
- data/protocol/amqp-0.8.xml +0 -3908
data/README.markdown
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
# Bunny: A synchronous Ruby AMQP client
|
2
2
|
|
3
|
-
Google Group: [bunny-amqp](http://groups.google.com/group/bunny-amqp)
|
3
|
+
Google Group: [http://groups.google.com/group/bunny-amqp](http://groups.google.com/group/bunny-amqp)
|
4
4
|
|
5
|
-
Mailing List: [bunny-amqp-devel](http://rubyforge.org/mailman/listinfo/bunny-amqp-devel)
|
5
|
+
Mailing List: [http://rubyforge.org/mailman/listinfo/bunny-amqp-devel](http://rubyforge.org/mailman/listinfo/bunny-amqp-devel)
|
6
6
|
|
7
|
-
Rubyforge: [bunny-amqp](http://rubyforge.org/projects/bunny-amqp)
|
7
|
+
Rubyforge: [http://rubyforge.org/projects/bunny-amqp](http://rubyforge.org/projects/bunny-amqp)
|
8
|
+
|
9
|
+
Twitter: [http://twitter.com/bunny_amqp](https://twitter.com/bunny_amqp)
|
8
10
|
|
9
11
|
## Announcements
|
10
12
|
|
11
|
-
Bunny v0.
|
13
|
+
Bunny v0.2.0 is now available. The highlights are -
|
12
14
|
|
13
|
-
*
|
14
|
-
*
|
15
|
-
* Queue#
|
16
|
-
* Queue#ack works after a Queue#subscribe or Queue#pop if :ack => true was specified
|
15
|
+
* Code has been re-organised enabling Bunny to play nicely with [amqp](http://github.com/tmm1/amqp) (thanks [Dan](http://github.com/danielsdeleo))
|
16
|
+
* When instantiating a default exchange (one beginning with ‘amq.’) the type will be inferred from the name.
|
17
|
+
* Fixed Queue#subscribe and included Queue#unsubscribe method. See examples/simple_consumer.rb for details
|
17
18
|
|
18
19
|
## About
|
19
20
|
|
@@ -92,6 +93,12 @@ Queue#publish(_**data**_, {_options_})
|
|
92
93
|
### Pop a message off of a queue
|
93
94
|
Queue#pop({_options_})
|
94
95
|
|
96
|
+
### Subscribe to a queue
|
97
|
+
Queue#subscribe({_options_}, &blk)
|
98
|
+
|
99
|
+
### Unsubscribe from a queue
|
100
|
+
Queue#unsubscribe({_options_})
|
101
|
+
|
95
102
|
### Return queue message count
|
96
103
|
Queue#message_count
|
97
104
|
|
data/examples/simple_consumer.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# consumer.rb
|
2
2
|
|
3
|
-
# N.B. To be used in conjunction with
|
3
|
+
# N.B. To be used in conjunction with simple_publisher.rb
|
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'.
|
@@ -8,6 +8,21 @@
|
|
8
8
|
# If this is not the case, please change the 'Bunny.new' call below to include
|
9
9
|
# the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
|
10
10
|
|
11
|
+
# How this example works
|
12
|
+
#=======================
|
13
|
+
#
|
14
|
+
# Open up two console windows start this program in one of them by typing -
|
15
|
+
#
|
16
|
+
# ruby simple_consumer.rb
|
17
|
+
#
|
18
|
+
# Then switch to the other console window and type -
|
19
|
+
#
|
20
|
+
# ruby simple_publisher.rb
|
21
|
+
#
|
22
|
+
# A message will be printed out by the simple_consumer and it will wait for the next message
|
23
|
+
#
|
24
|
+
# Run simple_publisher 3 more times. After the last run simple_consumer will stop.
|
25
|
+
|
11
26
|
$:.unshift File.dirname(__FILE__) + '/../lib'
|
12
27
|
|
13
28
|
require 'bunny'
|
@@ -26,11 +41,15 @@ exch = b.exchange('sorting_room')
|
|
26
41
|
# bind queue to exchange
|
27
42
|
q.bind(exch, :key => 'fred')
|
28
43
|
|
29
|
-
#
|
30
|
-
|
44
|
+
# initialize counter
|
45
|
+
i = 1
|
31
46
|
|
32
|
-
#
|
33
|
-
|
47
|
+
# subscribe to queue
|
48
|
+
q.subscribe(:consumer_tag => 'testtag1') do |msg|
|
49
|
+
puts i.to_s + ': ' + msg
|
50
|
+
i+=1
|
51
|
+
q.unsubscribe(:consumer_tag => 'testtag1') if i == 5
|
52
|
+
end
|
34
53
|
|
35
54
|
# close the connection
|
36
55
|
b.stop
|
@@ -13,12 +13,7 @@ require 'bunny'
|
|
13
13
|
b = Bunny.new(:logging => true)
|
14
14
|
|
15
15
|
# start a communication session with the amqp server
|
16
|
-
|
17
|
-
b.start
|
18
|
-
rescue Exception => e
|
19
|
-
puts 'ERROR - Could not start a session: ' + e
|
20
|
-
exit
|
21
|
-
end
|
16
|
+
b.start
|
22
17
|
|
23
18
|
# declare queues
|
24
19
|
q1 = b.queue('test_fan1')
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# simple_publisher.rb
|
2
2
|
|
3
|
-
# N.B. To be used in conjunction with simple_consumer.rb
|
3
|
+
# N.B. To be used in conjunction with simple_consumer.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'.
|
@@ -17,15 +17,9 @@ b = Bunny.new(:logging => true)
|
|
17
17
|
# start a communication session with the amqp server
|
18
18
|
b.start
|
19
19
|
|
20
|
-
# create/get queue
|
21
|
-
q = b.queue('po_box')
|
22
|
-
|
23
20
|
# create/get exchange
|
24
21
|
exch = b.exchange('sorting_room')
|
25
22
|
|
26
|
-
# bind queue to exchange
|
27
|
-
q.bind(exch, :key => 'fred')
|
28
|
-
|
29
23
|
# publish message to exchange
|
30
24
|
exch.publish('This is a message from the publisher', :key => 'fred')
|
31
25
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# simple_topic.rb
|
2
|
+
|
3
|
+
# Assumes that target message broker/server has a user called 'guest' with a password 'guest'
|
4
|
+
# and that it is running on 'localhost'.
|
5
|
+
|
6
|
+
# If this is not the case, please change the 'Bunny.new' call below to include
|
7
|
+
# the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
|
8
|
+
|
9
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
10
|
+
|
11
|
+
require 'bunny'
|
12
|
+
|
13
|
+
b = Bunny.new
|
14
|
+
|
15
|
+
# start a communication session with the amqp server
|
16
|
+
b.start
|
17
|
+
|
18
|
+
# declare queues
|
19
|
+
soccer = b.queue('topic_soccer')
|
20
|
+
cricket = b.queue('topic_cricket')
|
21
|
+
rugby = b.queue('topic_rugby')
|
22
|
+
allsport = b.queue('topic_allsport')
|
23
|
+
|
24
|
+
# create a topic exchange
|
25
|
+
sports_results = b.exchange('sports_results', :type => :topic)
|
26
|
+
|
27
|
+
# bind the queues to the exchange
|
28
|
+
soccer.bind(sports_results, :key => 'soccer.*')
|
29
|
+
cricket.bind(sports_results, :key => 'cricket.*')
|
30
|
+
rugby.bind(sports_results, :key => 'rugby.*')
|
31
|
+
allsport.bind(sports_results, :key => '*.result')
|
32
|
+
|
33
|
+
# publish messages to the exchange
|
34
|
+
sports_results.publish('Manchester United 1 : Hull City 4', :key => 'soccer.result')
|
35
|
+
sports_results.publish('England beat Australia by 5 wickets in first test', :key => 'cricket.result')
|
36
|
+
sports_results.publish('British Lions 15 : South Africa 12', :key => 'rugby.result')
|
37
|
+
|
38
|
+
# get message from the queues
|
39
|
+
|
40
|
+
# soccer queue got the soccer message
|
41
|
+
msg = soccer.pop
|
42
|
+
puts 'This is a message from the soccer q: ' + msg + "\n\n"
|
43
|
+
|
44
|
+
# cricket queue got the cricket message
|
45
|
+
msg = cricket.pop
|
46
|
+
puts 'This is a message from the cricket q: ' + msg + "\n\n"
|
47
|
+
|
48
|
+
# rugby queue got the rugby message
|
49
|
+
msg = rugby.pop
|
50
|
+
puts 'This is a message from the rugby q: ' + msg + "\n\n"
|
51
|
+
|
52
|
+
# allsport queue got all of the messages
|
53
|
+
until msg == 'QUEUE EMPTY' do
|
54
|
+
msg = allsport.pop
|
55
|
+
puts 'This is a message from the allsport q: ' + msg + "\n\n" unless msg == 'QUEUE EMPTY'
|
56
|
+
end
|
57
|
+
|
58
|
+
# close the client connection
|
59
|
+
b.stop
|
data/lib/bunny.rb
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
$:.unshift File.expand_path(File.dirname(__FILE__))
|
2
2
|
|
3
|
-
|
3
|
+
# Ruby standard libraries
|
4
|
+
%w[socket thread timeout].each do |file|
|
4
5
|
require file
|
5
6
|
end
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
# AMQP protocol and transport
|
9
|
+
%w[spec protocol buffer frame].each do |file|
|
10
|
+
require 'engineroom/' + file
|
9
11
|
end
|
10
12
|
|
13
|
+
# Bunny API
|
14
|
+
%w[client exchange header queue].each do |file|
|
15
|
+
require 'bunny/' + file
|
16
|
+
end
|
17
|
+
|
18
|
+
# Error and return message definitions
|
19
|
+
require 'api_messages'
|
20
|
+
|
11
21
|
class Bunny
|
12
|
-
|
22
|
+
include Protocol
|
23
|
+
include Transport
|
24
|
+
include API
|
25
|
+
|
13
26
|
attr_reader :client
|
14
27
|
|
15
28
|
def initialize(opts = {})
|
16
|
-
@client =
|
29
|
+
@client = API::Client.new(opts)
|
17
30
|
end
|
18
31
|
|
19
32
|
def logging=(bool)
|
@@ -33,11 +46,11 @@ class Bunny
|
|
33
46
|
end
|
34
47
|
|
35
48
|
def exchange(name, opts = {})
|
36
|
-
client.exchanges[name] ||= Exchange.new(client, name, opts)
|
49
|
+
client.exchanges[name] ||= API::Exchange.new(client, name, opts)
|
37
50
|
end
|
38
51
|
|
39
52
|
def queue(name, opts = {})
|
40
|
-
client.queues[name] ||= Queue.new(client, name, opts)
|
53
|
+
client.queues[name] ||= API::Queue.new(client, name, opts)
|
41
54
|
end
|
42
55
|
|
43
56
|
def stop
|
@@ -63,5 +76,5 @@ class Bunny
|
|
63
76
|
def port
|
64
77
|
client.port
|
65
78
|
end
|
66
|
-
|
79
|
+
|
67
80
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module API
|
2
2
|
class Client
|
3
3
|
CONNECT_TIMEOUT = 1.0
|
4
4
|
RETRY_DELAY = 10.0
|
@@ -8,7 +8,7 @@ module AMQP
|
|
8
8
|
|
9
9
|
def initialize(opts = {})
|
10
10
|
@host = opts[:host] || 'localhost'
|
11
|
-
@port = opts[:port] ||
|
11
|
+
@port = opts[:port] || Protocol::PORT
|
12
12
|
@user = opts[:user] || 'guest'
|
13
13
|
@pass = opts[:pass] || 'guest'
|
14
14
|
@vhost = opts[:vhost] || '/'
|
@@ -28,7 +28,7 @@ module AMQP
|
|
28
28
|
def send_frame(*args)
|
29
29
|
args.each do |data|
|
30
30
|
data.ticket = ticket if ticket and data.respond_to?(:ticket=)
|
31
|
-
data = data.to_frame(channel) unless data.is_a?(Frame)
|
31
|
+
data = data.to_frame(channel) unless data.is_a?(Transport::Frame)
|
32
32
|
data.channel = channel
|
33
33
|
|
34
34
|
log :send, data
|
@@ -38,7 +38,7 @@ module AMQP
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def next_frame
|
41
|
-
frame = Frame.parse(buffer)
|
41
|
+
frame = Transport::Frame.parse(buffer)
|
42
42
|
log :received, frame
|
43
43
|
frame
|
44
44
|
end
|
@@ -56,13 +56,13 @@ module AMQP
|
|
56
56
|
send_frame(
|
57
57
|
Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
|
58
58
|
)
|
59
|
-
raise ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Protocol::Channel::CloseOk)
|
59
|
+
raise API::ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Protocol::Channel::CloseOk)
|
60
60
|
|
61
61
|
self.channel = 0
|
62
62
|
send_frame(
|
63
63
|
Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
64
64
|
)
|
65
|
-
raise ProtocolError, "Error closing connection" unless next_method.is_a?(Protocol::Connection::CloseOk)
|
65
|
+
raise API::ProtocolError, "Error closing connection" unless next_method.is_a?(Protocol::Connection::CloseOk)
|
66
66
|
|
67
67
|
close_socket
|
68
68
|
end
|
@@ -77,9 +77,9 @@ module AMQP
|
|
77
77
|
|
78
78
|
def start_session
|
79
79
|
@channel = 0
|
80
|
-
write(HEADER)
|
81
|
-
write([1, 1, VERSION_MAJOR, VERSION_MINOR].pack('C4'))
|
82
|
-
raise ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Protocol::Connection::Start)
|
80
|
+
write(Protocol::HEADER)
|
81
|
+
write([1, 1, Protocol::VERSION_MAJOR, Protocol::VERSION_MINOR].pack('C4'))
|
82
|
+
raise API::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Protocol::Connection::Start)
|
83
83
|
|
84
84
|
send_frame(
|
85
85
|
Protocol::Connection::StartOk.new(
|
@@ -91,7 +91,7 @@ module AMQP
|
|
91
91
|
)
|
92
92
|
|
93
93
|
method = next_method
|
94
|
-
raise ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
94
|
+
raise API::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
95
95
|
|
96
96
|
if method.is_a?(Protocol::Connection::Tune)
|
97
97
|
send_frame(
|
@@ -102,17 +102,17 @@ module AMQP
|
|
102
102
|
send_frame(
|
103
103
|
Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
|
104
104
|
)
|
105
|
-
raise ProtocolError, 'Cannot open connection' unless next_method.is_a?(Protocol::Connection::OpenOk)
|
105
|
+
raise API::ProtocolError, 'Cannot open connection' unless next_method.is_a?(Protocol::Connection::OpenOk)
|
106
106
|
|
107
107
|
@channel = 1
|
108
108
|
send_frame(Protocol::Channel::Open.new)
|
109
|
-
raise ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Protocol::Channel::OpenOk)
|
109
|
+
raise API::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Protocol::Channel::OpenOk)
|
110
110
|
|
111
111
|
send_frame(
|
112
112
|
Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
|
113
113
|
)
|
114
114
|
method = next_method
|
115
|
-
raise ProtocolError, 'Access denied' unless method.is_a?(Protocol::Access::RequestOk)
|
115
|
+
raise API::ProtocolError, 'Access denied' unless method.is_a?(Protocol::Access::RequestOk)
|
116
116
|
self.ticket = method.ticket
|
117
117
|
|
118
118
|
# return status
|
@@ -122,14 +122,14 @@ module AMQP
|
|
122
122
|
private
|
123
123
|
|
124
124
|
def buffer
|
125
|
-
@buffer ||= Buffer.new(self)
|
125
|
+
@buffer ||= Transport::Buffer.new(self)
|
126
126
|
end
|
127
127
|
|
128
128
|
def send_command(cmd, *args)
|
129
129
|
begin
|
130
130
|
socket.__send__(cmd, *args)
|
131
131
|
rescue Errno::EPIPE, IOError => e
|
132
|
-
raise ServerDownError, e.message
|
132
|
+
raise API::ServerDownError, e.message
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
@@ -147,7 +147,7 @@ module AMQP
|
|
147
147
|
end
|
148
148
|
@status = CONNECTED
|
149
149
|
rescue SocketError, SystemCallError, IOError, Timeout::Error => e
|
150
|
-
raise ServerDownError, e.message
|
150
|
+
raise API::ServerDownError, e.message
|
151
151
|
end
|
152
152
|
|
153
153
|
@socket
|
data/lib/bunny/exchange.rb
CHANGED
@@ -1,16 +1,24 @@
|
|
1
|
-
|
1
|
+
module API
|
2
2
|
class Exchange
|
3
3
|
|
4
|
-
include AMQP
|
5
|
-
|
6
4
|
attr_reader :client, :type, :name, :opts, :key
|
7
5
|
|
8
6
|
def initialize(client, name, opts = {})
|
9
7
|
# check connection to server
|
10
|
-
raise ConnectionError, 'Not connected to server' if client.status == NOT_CONNECTED
|
8
|
+
raise API::ConnectionError, 'Not connected to server' if client.status == NOT_CONNECTED
|
11
9
|
|
12
10
|
@client, @name, @opts = client, name, opts
|
13
|
-
|
11
|
+
|
12
|
+
# set up the exchange type catering for default names
|
13
|
+
if name.match(/^amq\./)
|
14
|
+
new_type = name.sub(/amq\./, '')
|
15
|
+
# handle 'amq.match' default
|
16
|
+
new_type = 'headers' if new_type == 'match'
|
17
|
+
@type = new_type.to_sym
|
18
|
+
else
|
19
|
+
@type = opts[:type] || :direct
|
20
|
+
end
|
21
|
+
|
14
22
|
@key = opts[:key]
|
15
23
|
@client.exchanges[@name] ||= self
|
16
24
|
|
@@ -25,7 +33,7 @@ class Bunny
|
|
25
33
|
)
|
26
34
|
)
|
27
35
|
|
28
|
-
raise ProtocolError,
|
36
|
+
raise API::ProtocolError,
|
29
37
|
"Error declaring exchange #{name}: type = #{type}" unless
|
30
38
|
client.next_method.is_a?(Protocol::Exchange::DeclareOk)
|
31
39
|
end
|
@@ -46,7 +54,7 @@ class Bunny
|
|
46
54
|
:priority => 0
|
47
55
|
}.merge(opts)
|
48
56
|
)
|
49
|
-
out << Frame::Body.new(data)
|
57
|
+
out << Transport::Frame::Body.new(data)
|
50
58
|
|
51
59
|
client.send_frame(*out)
|
52
60
|
end
|
@@ -60,7 +68,7 @@ class Bunny
|
|
60
68
|
Protocol::Exchange::Delete.new({ :exchange => name, :nowait => false }.merge(opts))
|
61
69
|
)
|
62
70
|
|
63
|
-
raise ProtocolError,
|
71
|
+
raise API::ProtocolError,
|
64
72
|
"Error deleting exchange #{name}" unless
|
65
73
|
client.next_method.is_a?(Protocol::Exchange::DeleteOk)
|
66
74
|
|
data/lib/bunny/header.rb
CHANGED
data/lib/bunny/queue.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
|
-
|
1
|
+
module API
|
2
2
|
class Queue
|
3
3
|
|
4
|
-
include AMQP
|
5
|
-
|
6
4
|
attr_reader :name, :client
|
7
5
|
attr_accessor :delivery_tag
|
8
6
|
|
9
7
|
def initialize(client, name, opts = {})
|
10
8
|
# check connection to server
|
11
|
-
raise ConnectionError, 'Not connected to server' if client.status == NOT_CONNECTED
|
9
|
+
raise API::ConnectionError, 'Not connected to server' if client.status == NOT_CONNECTED
|
12
10
|
|
13
11
|
@client = client
|
14
12
|
@opts = opts
|
15
13
|
@name = name
|
14
|
+
@delivery_tag = nil
|
16
15
|
|
17
16
|
# ignore the :nowait option if passed, otherwise program will hang waiting for a
|
18
17
|
# response that will not be sent by the server
|
@@ -22,7 +21,7 @@ class Bunny
|
|
22
21
|
Protocol::Queue::Declare.new({ :queue => name, :nowait => false }.merge(opts))
|
23
22
|
)
|
24
23
|
|
25
|
-
raise ProtocolError, "Error declaring queue #{name}" unless client.next_method.is_a?(Protocol::Queue::DeclareOk)
|
24
|
+
raise API::ProtocolError, "Error declaring queue #{name}" unless client.next_method.is_a?(Protocol::Queue::DeclareOk)
|
26
25
|
end
|
27
26
|
|
28
27
|
def ack
|
@@ -54,7 +53,7 @@ class Bunny
|
|
54
53
|
if method.is_a?(Protocol::Basic::GetEmpty) then
|
55
54
|
return QUEUE_EMPTY
|
56
55
|
elsif !method.is_a?(Protocol::Basic::GetOk)
|
57
|
-
raise ProtocolError, "Error getting message from queue #{name}"
|
56
|
+
raise API::ProtocolError, "Error getting message from queue #{name}"
|
58
57
|
end
|
59
58
|
|
60
59
|
# get delivery tag to use for acknowledge
|
@@ -62,7 +61,7 @@ class Bunny
|
|
62
61
|
|
63
62
|
header = client.next_payload
|
64
63
|
msg = client.next_payload
|
65
|
-
raise MessageError, 'unexpected length' if msg.length < header.size
|
64
|
+
raise API::MessageError, 'unexpected length' if msg.length < header.size
|
66
65
|
|
67
66
|
hdr ? {:header => header, :payload => msg} : msg
|
68
67
|
|
@@ -90,7 +89,7 @@ class Bunny
|
|
90
89
|
{:message_count => method.message_count, :consumer_count => method.consumer_count}
|
91
90
|
end
|
92
91
|
|
93
|
-
def subscribe(opts = {})
|
92
|
+
def subscribe(opts = {}, &blk)
|
94
93
|
consumer_tag = opts[:consumer_tag] || name
|
95
94
|
|
96
95
|
# ignore the :nowait option if passed, otherwise program will not wait for a
|
@@ -110,21 +109,31 @@ class Bunny
|
|
110
109
|
:nowait => false }.merge(opts))
|
111
110
|
)
|
112
111
|
|
113
|
-
raise ProtocolError,
|
112
|
+
raise API::ProtocolError,
|
114
113
|
"Error subscribing to queue #{name}" unless
|
115
114
|
client.next_method.is_a?(Protocol::Basic::ConsumeOk)
|
116
115
|
|
117
|
-
|
116
|
+
while true
|
117
|
+
method = client.next_method
|
118
|
+
break if method.is_a?(Protocol::Basic::CancelOk)
|
118
119
|
|
119
|
-
|
120
|
-
|
120
|
+
# get delivery tag to use for acknowledge
|
121
|
+
self.delivery_tag = method.delivery_tag if ack
|
122
|
+
|
123
|
+
header = client.next_payload
|
124
|
+
msg = client.next_payload
|
125
|
+
raise API::MessageError, 'unexpected length' if msg.length < header.size
|
126
|
+
|
127
|
+
# pass the message to the block for processing
|
128
|
+
blk.call(hdr ? {:header => header, :payload => msg} : msg)
|
129
|
+
end
|
121
130
|
|
122
|
-
header = client.next_payload
|
123
|
-
msg = client.next_payload
|
124
|
-
raise MessageError, 'unexpected length' if msg.length < header.size
|
125
|
-
|
126
|
-
hdr ? {:header => header, :payload => msg} : msg
|
127
131
|
end
|
132
|
+
|
133
|
+
def unsubscribe(opts = {})
|
134
|
+
consumer_tag = opts[:consumer_tag] || name
|
135
|
+
client.send_frame( Protocol::Basic::Cancel.new({ :consumer_tag => consumer_tag }.merge(opts)))
|
136
|
+
end
|
128
137
|
|
129
138
|
def bind(exchange, opts = {})
|
130
139
|
exchange = exchange.respond_to?(:name) ? exchange.name : exchange
|
@@ -141,7 +150,7 @@ class Bunny
|
|
141
150
|
:nowait => false }.merge(opts))
|
142
151
|
)
|
143
152
|
|
144
|
-
raise ProtocolError,
|
153
|
+
raise API::ProtocolError,
|
145
154
|
"Error binding queue #{name}" unless
|
146
155
|
client.next_method.is_a?(Protocol::Queue::BindOk)
|
147
156
|
|
@@ -161,7 +170,7 @@ class Bunny
|
|
161
170
|
)
|
162
171
|
)
|
163
172
|
|
164
|
-
raise ProtocolError,
|
173
|
+
raise API::ProtocolError,
|
165
174
|
"Error unbinding queue #{name}" unless
|
166
175
|
client.next_method.is_a?(Protocol::Queue::UnbindOk)
|
167
176
|
|
@@ -178,7 +187,7 @@ class Bunny
|
|
178
187
|
Protocol::Queue::Delete.new({ :queue => name, :nowait => false }.merge(opts))
|
179
188
|
)
|
180
189
|
|
181
|
-
raise ProtocolError,
|
190
|
+
raise API::ProtocolError,
|
182
191
|
"Error deleting queue #{name}" unless
|
183
192
|
client.next_method.is_a?(Protocol::Queue::DeleteOk)
|
184
193
|
|