bunny 0.1.1 → 0.2.0
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/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
|
|