celldee-bunny 0.2.0 → 0.3.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/LICENSE +20 -0
- data/README +49 -0
- data/Rakefile +3 -4
- data/bunny.gemspec +37 -0
- data/examples/simple.rb +1 -1
- data/examples/simple_ack.rb +1 -1
- data/examples/simple_consumer.rb +1 -1
- data/examples/simple_fanout.rb +1 -1
- data/examples/simple_publisher.rb +1 -1
- data/examples/simple_topic.rb +3 -3
- data/ext/codegen.rb +177 -0
- data/lib/bunny/client.rb +161 -14
- data/lib/bunny/exchange.rb +155 -80
- data/lib/bunny/protocol/protocol.rb +135 -0
- data/lib/bunny/protocol/spec.rb +836 -0
- data/lib/bunny/queue.rb +223 -23
- data/lib/bunny/transport/buffer.rb +266 -0
- data/lib/bunny/transport/frame.rb +62 -0
- data/lib/bunny.rb +20 -62
- data/spec/bunny_spec.rb +2 -2
- data/spec/exchange_spec.rb +3 -3
- data/spec/queue_spec.rb +10 -9
- metadata +22 -22
- data/README.markdown +0 -126
- data/lib/api_messages.rb +0 -18
- data/lib/bunny/header.rb +0 -30
- data/lib/engineroom/buffer.rb +0 -274
- data/lib/engineroom/frame.rb +0 -61
- data/lib/engineroom/protocol.rb +0 -156
- data/lib/engineroom/spec.rb +0 -830
- data/protocol/codegen.rb +0 -171
- /data/{protocol → ext}/amqp-0.8.json +0 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 Chris Duncan
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
= Bunny: A synchronous Ruby AMQP client
|
|
2
|
+
|
|
3
|
+
*GitHub* *repo*: http://github.com/celldee/bunny
|
|
4
|
+
|
|
5
|
+
=== DESCRIPTION:
|
|
6
|
+
|
|
7
|
+
Bunny is an AMQP[http://www.amqp.org] (Advanced Message Queuing Protocol) client, written in Ruby, that is intended to allow you to interact with AMQP-compliant message brokers/servers such as RabbitMQ[http://www.rabbitmq.com] in a synchronous fashion.
|
|
8
|
+
|
|
9
|
+
It is based on a great deal of useful code from amqp[http://github.com/tmm1/amqp] by Aman Gupta and Carrot[http://github.com/famoseagle/carrot] by Amos Elliston.
|
|
10
|
+
|
|
11
|
+
You can use Bunny to -
|
|
12
|
+
|
|
13
|
+
* Create and delete exchanges
|
|
14
|
+
* Create and delete queues
|
|
15
|
+
* Publish and consume messages
|
|
16
|
+
|
|
17
|
+
Bunny is known to work with RabbitMQ version 1.5.4 and version 0-8 of the AMQP specification.
|
|
18
|
+
|
|
19
|
+
=== INSTALL:
|
|
20
|
+
|
|
21
|
+
*Rubyforge*: <tt>gem install bunny</tt>
|
|
22
|
+
|
|
23
|
+
*GitHub*: <tt>gem install celldee-bunny</tt>
|
|
24
|
+
|
|
25
|
+
=== QUICK START:
|
|
26
|
+
|
|
27
|
+
require 'bunny'
|
|
28
|
+
|
|
29
|
+
b = Bunny::Client.new(:logging => true)
|
|
30
|
+
|
|
31
|
+
# start a communication session with the amqp server
|
|
32
|
+
b.start
|
|
33
|
+
|
|
34
|
+
# declare a queue
|
|
35
|
+
q = b.queue('test1')
|
|
36
|
+
|
|
37
|
+
# publish a message to the queue
|
|
38
|
+
q.publish('Hello everybody!')
|
|
39
|
+
|
|
40
|
+
# get message from the queue
|
|
41
|
+
msg = q.pop
|
|
42
|
+
|
|
43
|
+
puts 'This is the message: ' + msg + "\n\n"
|
|
44
|
+
|
|
45
|
+
# close the connection
|
|
46
|
+
b.stop
|
|
47
|
+
|
|
48
|
+
=== OTHER:
|
|
49
|
+
Please see the _examples_ directory for additional usage information.
|
data/Rakefile
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
task :codegen do
|
|
2
|
-
sh 'ruby
|
|
3
|
-
sh 'ruby lib/
|
|
2
|
+
sh 'ruby ext/codegen.rb > lib/bunny/protocol/spec.rb'
|
|
3
|
+
sh 'ruby lib/bunny/protocol/spec.rb'
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
task :spec do
|
|
@@ -8,5 +8,4 @@ task :spec do
|
|
|
8
8
|
Spec::Rake::SpecTask.new do |t|
|
|
9
9
|
t.spec_opts = ['--color']
|
|
10
10
|
end
|
|
11
|
-
end
|
|
12
|
-
|
|
11
|
+
end
|
data/bunny.gemspec
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = %q{bunny}
|
|
3
|
+
s.version = "0.3.0"
|
|
4
|
+
s.authors = ["Chris Duncan"]
|
|
5
|
+
s.date = %q{2009-05-10}
|
|
6
|
+
s.description = %q{Another synchronous Ruby AMQP client}
|
|
7
|
+
s.email = %q{celldee@gmail.com}
|
|
8
|
+
s.rubyforge_project = %q{bunny-amqp}
|
|
9
|
+
s.has_rdoc = true
|
|
10
|
+
s.extra_rdoc_files = [ "README" ]
|
|
11
|
+
s.rdoc_options = [ "--main", "README" ]
|
|
12
|
+
s.homepage = %q{http://github.com/celldee/bunny}
|
|
13
|
+
s.summary = %q{A synchronous Ruby AMQP client that enables interaction with AMQP-compliant brokers/servers.}
|
|
14
|
+
s.files = ["LICENSE",
|
|
15
|
+
"README",
|
|
16
|
+
"Rakefile",
|
|
17
|
+
"bunny.gemspec",
|
|
18
|
+
"examples/simple.rb",
|
|
19
|
+
"examples/simple_ack.rb",
|
|
20
|
+
"examples/simple_consumer.rb",
|
|
21
|
+
"examples/simple_fanout.rb",
|
|
22
|
+
"examples/simple_publisher.rb",
|
|
23
|
+
"examples/simple_topic.rb",
|
|
24
|
+
"ext/amqp-0.8.json",
|
|
25
|
+
"ext/codegen.rb",
|
|
26
|
+
"lib/bunny.rb",
|
|
27
|
+
"lib/bunny/client.rb",
|
|
28
|
+
"lib/bunny/exchange.rb",
|
|
29
|
+
"lib/bunny/protocol/protocol.rb",
|
|
30
|
+
"lib/bunny/protocol/spec.rb",
|
|
31
|
+
"lib/bunny/queue.rb",
|
|
32
|
+
"lib/bunny/transport/buffer.rb",
|
|
33
|
+
"lib/bunny/transport/frame.rb",
|
|
34
|
+
"spec/bunny_spec.rb",
|
|
35
|
+
"spec/exchange_spec.rb",
|
|
36
|
+
"spec/queue_spec.rb"]
|
|
37
|
+
end
|
data/examples/simple.rb
CHANGED
data/examples/simple_ack.rb
CHANGED
data/examples/simple_consumer.rb
CHANGED
data/examples/simple_fanout.rb
CHANGED
data/examples/simple_topic.rb
CHANGED
|
@@ -10,7 +10,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
|
|
|
10
10
|
|
|
11
11
|
require 'bunny'
|
|
12
12
|
|
|
13
|
-
b = Bunny.new
|
|
13
|
+
b = Bunny::Client.new
|
|
14
14
|
|
|
15
15
|
# start a communication session with the amqp server
|
|
16
16
|
b.start
|
|
@@ -50,9 +50,9 @@ msg = rugby.pop
|
|
|
50
50
|
puts 'This is a message from the rugby q: ' + msg + "\n\n"
|
|
51
51
|
|
|
52
52
|
# allsport queue got all of the messages
|
|
53
|
-
until msg ==
|
|
53
|
+
until msg == :queue_empty do
|
|
54
54
|
msg = allsport.pop
|
|
55
|
-
puts 'This is a message from the allsport q: ' + msg + "\n\n" unless msg ==
|
|
55
|
+
puts 'This is a message from the allsport q: ' + msg + "\n\n" unless msg == :queue_empty
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
# close the client connection
|
data/ext/codegen.rb
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
name = 'amqp-0.8.json'
|
|
5
|
+
path = File.dirname(__FILE__)+'/'+name
|
|
6
|
+
s = JSON.parse(File.read(path))
|
|
7
|
+
|
|
8
|
+
# require 'pp'
|
|
9
|
+
# pp(s)
|
|
10
|
+
# exit
|
|
11
|
+
|
|
12
|
+
require 'erb'
|
|
13
|
+
|
|
14
|
+
puts ERB.new(%q[
|
|
15
|
+
#:stopdoc:
|
|
16
|
+
# this file was autogenerated on <%= Time.now.to_s %>
|
|
17
|
+
# using <%= name.ljust(16) %> (mtime: <%= File.mtime(path) %>)
|
|
18
|
+
#
|
|
19
|
+
# DO NOT EDIT! (edit ext/codegen.rb instead, and run `rake codegen`)
|
|
20
|
+
|
|
21
|
+
module Bunny
|
|
22
|
+
module Transport
|
|
23
|
+
class Frame
|
|
24
|
+
def self.types
|
|
25
|
+
@types ||= {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.Frame id
|
|
29
|
+
(@_base_frames ||= {})[id] ||= Class.new(Frame) do
|
|
30
|
+
class_eval %[
|
|
31
|
+
def self.inherited klass
|
|
32
|
+
klass.const_set(:ID, #{id})
|
|
33
|
+
Frame.types[#{id}] = klass
|
|
34
|
+
end
|
|
35
|
+
]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
<%- s['constants'].select{|c| (1..8).include? c['value'] }.each do |c| -%>
|
|
40
|
+
class <%= c['name'].gsub(/^FRAME-/,'').split('-').map{|w| w.downcase.capitalize}.join.ljust(9) -%> < Frame( <%= c['value'] -%> ); end
|
|
41
|
+
<%- end -%>
|
|
42
|
+
|
|
43
|
+
FOOTER = <%= frame_end = s['constants'].find{|c| c['name'] == 'FRAME-END' }['value'] %>
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module Bunny
|
|
49
|
+
module Protocol
|
|
50
|
+
HEADER = <%= s['name'].dump %>.freeze
|
|
51
|
+
VERSION_MAJOR = <%= s['major-version'] %>
|
|
52
|
+
VERSION_MINOR = <%= s['minor-version'] %>
|
|
53
|
+
PORT = <%= s['port'] %>
|
|
54
|
+
|
|
55
|
+
RESPONSES = {
|
|
56
|
+
<%- s['constants'].select{|c| c['value'] != frame_end and (200..500).include? c['value'] }.each do |c| -%>
|
|
57
|
+
<%= c['value'] %> => :<%= c['name'].tr('-', '_').gsub(/^FRAME_/,'').upcase -%>,
|
|
58
|
+
<%- end -%>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
FIELDS = [
|
|
62
|
+
<%- s['domains'].select{|d| d.first == d.last }.each do |d| -%>
|
|
63
|
+
:<%= d.first -%>,
|
|
64
|
+
<%- end -%>
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
class Class
|
|
68
|
+
class << self
|
|
69
|
+
FIELDS.each do |f|
|
|
70
|
+
class_eval %[
|
|
71
|
+
def #{f} name
|
|
72
|
+
properties << [ :#{f}, name ] unless properties.include?([:#{f}, name])
|
|
73
|
+
attr_accessor name
|
|
74
|
+
end
|
|
75
|
+
]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def properties() @properties ||= [] end
|
|
79
|
+
|
|
80
|
+
def id() self::ID end
|
|
81
|
+
def name() self::NAME end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class Method
|
|
85
|
+
class << self
|
|
86
|
+
FIELDS.each do |f|
|
|
87
|
+
class_eval %[
|
|
88
|
+
def #{f} name
|
|
89
|
+
arguments << [ :#{f}, name ] unless arguments.include?([:#{f}, name])
|
|
90
|
+
attr_accessor name
|
|
91
|
+
end
|
|
92
|
+
]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def arguments() @arguments ||= [] end
|
|
96
|
+
|
|
97
|
+
def parent() Protocol.const_get(self.to_s[/Protocol::(.+?)::/,1]) end
|
|
98
|
+
def id() self::ID end
|
|
99
|
+
def name() self::NAME end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def == b
|
|
103
|
+
self.class.arguments.inject(true) do |eql, (type, name)|
|
|
104
|
+
eql and __send__("#{name}") == b.__send__("#{name}")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def self.methods() @methods ||= {} end
|
|
110
|
+
|
|
111
|
+
def self.Method(id, name)
|
|
112
|
+
@_base_methods ||= {}
|
|
113
|
+
@_base_methods[id] ||= ::Class.new(Method) do
|
|
114
|
+
class_eval %[
|
|
115
|
+
def self.inherited klass
|
|
116
|
+
klass.const_set(:ID, #{id})
|
|
117
|
+
klass.const_set(:NAME, :#{name.to_s})
|
|
118
|
+
klass.parent.methods[#{id}] = klass
|
|
119
|
+
klass.parent.methods[klass::NAME] = klass
|
|
120
|
+
end
|
|
121
|
+
]
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def self.classes() @classes ||= {} end
|
|
127
|
+
|
|
128
|
+
def self.Class(id, name)
|
|
129
|
+
@_base_classes ||= {}
|
|
130
|
+
@_base_classes[id] ||= ::Class.new(Class) do
|
|
131
|
+
class_eval %[
|
|
132
|
+
def self.inherited klass
|
|
133
|
+
klass.const_set(:ID, #{id})
|
|
134
|
+
klass.const_set(:NAME, :#{name.to_s})
|
|
135
|
+
Protocol.classes[#{id}] = klass
|
|
136
|
+
Protocol.classes[klass::NAME] = klass
|
|
137
|
+
end
|
|
138
|
+
]
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
module Bunny
|
|
145
|
+
module Protocol
|
|
146
|
+
<%- s['classes'].each do |c| -%>
|
|
147
|
+
class <%= c['name'].capitalize.ljust(12) %> < Class( <%= c['id'].to_s.rjust(3) %>, :<%= c['name'].ljust(12) %> ); end
|
|
148
|
+
<%- end -%>
|
|
149
|
+
|
|
150
|
+
<%- s['classes'].each do |c| -%>
|
|
151
|
+
class <%= c['name'].capitalize %>
|
|
152
|
+
<%- c['properties'].each do |p| -%>
|
|
153
|
+
<%= p['type'].ljust(10) %> :<%= p['name'].tr('-','_') %>
|
|
154
|
+
<%- end if c['properties'] -%>
|
|
155
|
+
|
|
156
|
+
<%- c['methods'].each do |m| -%>
|
|
157
|
+
class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"}.ljust(12) %> < Method( <%= m['id'].to_s.rjust(3) %>, :<%= m['name'].tr('- ','_').ljust(14) %> ); end
|
|
158
|
+
<%- end -%>
|
|
159
|
+
|
|
160
|
+
<%- c['methods'].each do |m| -%>
|
|
161
|
+
class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"} %>
|
|
162
|
+
<%- m['arguments'].each do |a| -%>
|
|
163
|
+
<%- if a['domain'] -%>
|
|
164
|
+
<%= s['domains'].find{|k,v| k == a['domain']}.last.ljust(10) %> :<%= a['name'].tr('- ','_') %>
|
|
165
|
+
<%- else -%>
|
|
166
|
+
<%= a['type'].ljust(10) %> :<%= a['name'].tr('- ','_') %>
|
|
167
|
+
<%- end -%>
|
|
168
|
+
<%- end if m['arguments'] -%>
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
<%- end -%>
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
<%- end -%>
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
].gsub!(/^ /,''), nil, '>-%').result(binding)
|
data/lib/bunny/client.rb
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Bunny
|
|
2
|
+
|
|
3
|
+
=begin rdoc
|
|
4
|
+
|
|
5
|
+
=== DESCRIPTION:
|
|
6
|
+
|
|
7
|
+
The Client class provides the major Bunny API methods.
|
|
8
|
+
|
|
9
|
+
=end
|
|
10
|
+
|
|
2
11
|
class Client
|
|
3
12
|
CONNECT_TIMEOUT = 1.0
|
|
4
13
|
RETRY_DELAY = 10.0
|
|
@@ -6,6 +15,29 @@ module API
|
|
|
6
15
|
attr_reader :status, :host, :vhost, :port
|
|
7
16
|
attr_accessor :channel, :logging, :exchanges, :queues, :ticket
|
|
8
17
|
|
|
18
|
+
=begin rdoc
|
|
19
|
+
|
|
20
|
+
=== DESCRIPTION:
|
|
21
|
+
|
|
22
|
+
Sets up a Bunny::Client object ready for connection to a broker/server. _Client_._status_ is set to
|
|
23
|
+
<tt>:not_connected</tt>.
|
|
24
|
+
|
|
25
|
+
==== OPTIONS:
|
|
26
|
+
|
|
27
|
+
* <tt>:host => '_hostname_' (default = 'localhost')</tt>
|
|
28
|
+
* <tt>:port => _portno_ (default = 5672)</tt>
|
|
29
|
+
* <tt>:vhost => '_vhostname_' (default = '/')</tt>
|
|
30
|
+
* <tt>:user => '_username_' (default = 'guest')</tt>
|
|
31
|
+
* <tt>:pass => '_password_' (default = 'guest')</tt>
|
|
32
|
+
* <tt>:logging => true or false (_default_)</tt> - If set to _true_, session information is sent
|
|
33
|
+
to STDOUT.
|
|
34
|
+
* <tt>:insist => true or false (_default_)</tt> - In a configuration with multiple load-sharing
|
|
35
|
+
servers, the server may respond to a Connection.Open method with a Connection.Redirect. The insist
|
|
36
|
+
option, if set to _true_, tells the server that the client is insisting on a connection to the
|
|
37
|
+
specified server.
|
|
38
|
+
|
|
39
|
+
=end
|
|
40
|
+
|
|
9
41
|
def initialize(opts = {})
|
|
10
42
|
@host = opts[:host] || 'localhost'
|
|
11
43
|
@port = opts[:port] || Protocol::PORT
|
|
@@ -14,12 +46,97 @@ module API
|
|
|
14
46
|
@vhost = opts[:vhost] || '/'
|
|
15
47
|
@logging = opts[:logging] || false
|
|
16
48
|
@insist = opts[:insist]
|
|
17
|
-
@status =
|
|
49
|
+
@status = :not_connected
|
|
18
50
|
end
|
|
19
51
|
|
|
52
|
+
=begin rdoc
|
|
53
|
+
|
|
54
|
+
=== DESCRIPTION:
|
|
55
|
+
|
|
56
|
+
Declares an exchange to the broker/server. If the exchange does not exist, a new one is created
|
|
57
|
+
using the arguments passed in. If the exchange already exists, a reference to it is created, provided
|
|
58
|
+
that the arguments passed in do not conflict with the existing attributes of the exchange. If an error
|
|
59
|
+
occurs a _Bunny_::_ProtocolError_ is raised.
|
|
60
|
+
|
|
61
|
+
==== OPTIONS:
|
|
62
|
+
|
|
63
|
+
* <tt>:type => one of :direct (_default_), :fanout, :topic, :headers</tt>
|
|
64
|
+
* <tt>:passive => true or false</tt> - If set to _true_, the server will not create the exchange.
|
|
65
|
+
The client can use this to check whether an exchange exists without modifying the server state.
|
|
66
|
+
* <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new exchange, the exchange
|
|
67
|
+
will be marked as durable. Durable exchanges remain active when a server restarts. Non-durable
|
|
68
|
+
exchanges (transient exchanges) are purged if/when a server restarts.
|
|
69
|
+
* <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the exchange is deleted
|
|
70
|
+
when all queues have finished using it.
|
|
71
|
+
* <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
|
|
72
|
+
|
|
73
|
+
==== RETURNS:
|
|
74
|
+
|
|
75
|
+
Exchange
|
|
76
|
+
|
|
77
|
+
=end
|
|
78
|
+
|
|
79
|
+
def exchange(name, opts = {})
|
|
80
|
+
exchanges[name] ||= Bunny::Exchange.new(self, name, opts)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
=begin rdoc
|
|
84
|
+
|
|
85
|
+
=== DESCRIPTION:
|
|
86
|
+
|
|
87
|
+
Returns hash of exchanges declared by Bunny.
|
|
88
|
+
|
|
89
|
+
=end
|
|
90
|
+
|
|
20
91
|
def exchanges
|
|
21
92
|
@exchanges ||= {}
|
|
22
93
|
end
|
|
94
|
+
|
|
95
|
+
=begin rdoc
|
|
96
|
+
|
|
97
|
+
=== DESCRIPTION:
|
|
98
|
+
|
|
99
|
+
Declares a queue to the broker/server. If the queue does not exist, a new one is created
|
|
100
|
+
using the arguments passed in. If the queue already exists, a reference to it is created, provided
|
|
101
|
+
that the arguments passed in do not conflict with the existing attributes of the queue. If an error
|
|
102
|
+
occurs a _Bunny_::_ProtocolError_ is raised.
|
|
103
|
+
|
|
104
|
+
==== OPTIONS:
|
|
105
|
+
|
|
106
|
+
* <tt>:passive => true or false (_default_)</tt> - If set to _true_, the server will not create
|
|
107
|
+
the queue. The client can use this to check whether a queue exists without modifying the server
|
|
108
|
+
state.
|
|
109
|
+
* <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new queue, the
|
|
110
|
+
queue will be marked as durable. Durable queues remain active when a server restarts. Non-durable
|
|
111
|
+
queues (transient queues) are purged if/when a server restarts. Note that durable queues do not
|
|
112
|
+
necessarily hold persistent messages, although it does not make sense to send persistent messages
|
|
113
|
+
to a transient queue.
|
|
114
|
+
* <tt>:exclusive => true or false (_default_)</tt> - If set to _true_, requests an exclusive queue.
|
|
115
|
+
Exclusive queues may only be consumed from by the current connection. Setting the 'exclusive'
|
|
116
|
+
flag always implies 'auto-delete'.
|
|
117
|
+
* <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the queue is deleted
|
|
118
|
+
when all consumers have finished using it. Last consumer can be cancelled either explicitly
|
|
119
|
+
or because its channel is closed. If there has never been a consumer on the queue, it is not
|
|
120
|
+
deleted.
|
|
121
|
+
* <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
|
|
122
|
+
|
|
123
|
+
==== RETURNS:
|
|
124
|
+
|
|
125
|
+
Queue
|
|
126
|
+
|
|
127
|
+
=end
|
|
128
|
+
|
|
129
|
+
def queue(name, opts = {})
|
|
130
|
+
queues[name] ||= Bunny::Queue.new(self, name, opts)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
=begin rdoc
|
|
134
|
+
|
|
135
|
+
=== DESCRIPTION:
|
|
136
|
+
|
|
137
|
+
Returns hash of queues declared by Bunny.
|
|
138
|
+
|
|
139
|
+
=end
|
|
23
140
|
|
|
24
141
|
def queues
|
|
25
142
|
@queues ||= {}
|
|
@@ -49,24 +166,39 @@ module API
|
|
|
49
166
|
|
|
50
167
|
def next_payload
|
|
51
168
|
frame = next_frame
|
|
52
|
-
frame
|
|
169
|
+
frame.payload
|
|
53
170
|
end
|
|
54
171
|
|
|
172
|
+
=begin rdoc
|
|
173
|
+
|
|
174
|
+
=== DESCRIPTION:
|
|
175
|
+
|
|
176
|
+
Closes the current communication channel and connection. If an error occurs a
|
|
177
|
+
_Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:not_connected</tt>.
|
|
178
|
+
|
|
179
|
+
==== RETURNS:
|
|
180
|
+
|
|
181
|
+
<tt>:not_connected</tt> if successful.
|
|
182
|
+
|
|
183
|
+
=end
|
|
184
|
+
|
|
55
185
|
def close
|
|
56
186
|
send_frame(
|
|
57
187
|
Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
|
|
58
188
|
)
|
|
59
|
-
raise
|
|
189
|
+
raise Bunny::ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Protocol::Channel::CloseOk)
|
|
60
190
|
|
|
61
191
|
self.channel = 0
|
|
62
192
|
send_frame(
|
|
63
193
|
Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
|
|
64
194
|
)
|
|
65
|
-
raise
|
|
195
|
+
raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Protocol::Connection::CloseOk)
|
|
66
196
|
|
|
67
197
|
close_socket
|
|
68
198
|
end
|
|
69
199
|
|
|
200
|
+
alias stop close
|
|
201
|
+
|
|
70
202
|
def read(*args)
|
|
71
203
|
send_command(:read, *args)
|
|
72
204
|
end
|
|
@@ -75,11 +207,24 @@ module API
|
|
|
75
207
|
send_command(:write, *args)
|
|
76
208
|
end
|
|
77
209
|
|
|
210
|
+
=begin rdoc
|
|
211
|
+
|
|
212
|
+
=== DESCRIPTION:
|
|
213
|
+
|
|
214
|
+
Opens a communication channel and starts a connection. If an error occurs, a
|
|
215
|
+
_Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:connected</tt>.
|
|
216
|
+
|
|
217
|
+
==== RETURNS:
|
|
218
|
+
|
|
219
|
+
<tt>:connected</tt> if successful.
|
|
220
|
+
|
|
221
|
+
=end
|
|
222
|
+
|
|
78
223
|
def start_session
|
|
79
224
|
@channel = 0
|
|
80
225
|
write(Protocol::HEADER)
|
|
81
226
|
write([1, 1, Protocol::VERSION_MAJOR, Protocol::VERSION_MINOR].pack('C4'))
|
|
82
|
-
raise
|
|
227
|
+
raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Protocol::Connection::Start)
|
|
83
228
|
|
|
84
229
|
send_frame(
|
|
85
230
|
Protocol::Connection::StartOk.new(
|
|
@@ -91,7 +236,7 @@ module API
|
|
|
91
236
|
)
|
|
92
237
|
|
|
93
238
|
method = next_method
|
|
94
|
-
raise
|
|
239
|
+
raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
|
|
95
240
|
|
|
96
241
|
if method.is_a?(Protocol::Connection::Tune)
|
|
97
242
|
send_frame(
|
|
@@ -102,23 +247,25 @@ module API
|
|
|
102
247
|
send_frame(
|
|
103
248
|
Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
|
|
104
249
|
)
|
|
105
|
-
raise
|
|
250
|
+
raise Bunny::ProtocolError, 'Cannot open connection' unless next_method.is_a?(Protocol::Connection::OpenOk)
|
|
106
251
|
|
|
107
252
|
@channel = 1
|
|
108
253
|
send_frame(Protocol::Channel::Open.new)
|
|
109
|
-
raise
|
|
254
|
+
raise Bunny::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Protocol::Channel::OpenOk)
|
|
110
255
|
|
|
111
256
|
send_frame(
|
|
112
257
|
Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
|
|
113
258
|
)
|
|
114
259
|
method = next_method
|
|
115
|
-
raise
|
|
260
|
+
raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Protocol::Access::RequestOk)
|
|
116
261
|
self.ticket = method.ticket
|
|
117
262
|
|
|
118
263
|
# return status
|
|
119
264
|
status
|
|
120
265
|
end
|
|
121
266
|
|
|
267
|
+
alias start start_session
|
|
268
|
+
|
|
122
269
|
private
|
|
123
270
|
|
|
124
271
|
def buffer
|
|
@@ -129,7 +276,7 @@ module API
|
|
|
129
276
|
begin
|
|
130
277
|
socket.__send__(cmd, *args)
|
|
131
278
|
rescue Errno::EPIPE, IOError => e
|
|
132
|
-
raise
|
|
279
|
+
raise Bunny::ServerDownError, e.message
|
|
133
280
|
end
|
|
134
281
|
end
|
|
135
282
|
|
|
@@ -145,9 +292,9 @@ module API
|
|
|
145
292
|
if Socket.constants.include? 'TCP_NODELAY'
|
|
146
293
|
@socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
|
|
147
294
|
end
|
|
148
|
-
@status =
|
|
295
|
+
@status = :connected
|
|
149
296
|
rescue SocketError, SystemCallError, IOError, Timeout::Error => e
|
|
150
|
-
raise
|
|
297
|
+
raise Bunny::ServerDownError, e.message
|
|
151
298
|
end
|
|
152
299
|
|
|
153
300
|
@socket
|
|
@@ -157,7 +304,7 @@ module API
|
|
|
157
304
|
# Close the socket. The server is not considered dead.
|
|
158
305
|
@socket.close if @socket and not @socket.closed?
|
|
159
306
|
@socket = nil
|
|
160
|
-
@status =
|
|
307
|
+
@status = :not_connected
|
|
161
308
|
end
|
|
162
309
|
|
|
163
310
|
def log(*args)
|