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/{protocol → ext}/amqp-0.8.json +0 -0
- data/ext/codegen.rb +177 -0
- data/lib/bunny.rb +20 -62
- 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/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/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
|
File without changes
|
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.rb
CHANGED
@@ -5,76 +5,34 @@ $:.unshift File.expand_path(File.dirname(__FILE__))
|
|
5
5
|
require file
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
8
|
+
require 'bunny/client'
|
9
|
+
require 'bunny/exchange'
|
10
|
+
require 'bunny/queue'
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
require 'bunny/' + file
|
16
|
-
end
|
12
|
+
require 'bunny/protocol/spec'
|
13
|
+
require 'bunny/protocol/protocol'
|
17
14
|
|
18
|
-
|
19
|
-
require '
|
15
|
+
require 'bunny/transport/buffer'
|
16
|
+
require 'bunny/transport/frame'
|
20
17
|
|
21
|
-
|
18
|
+
module Bunny
|
19
|
+
|
22
20
|
include Protocol
|
23
21
|
include Transport
|
24
|
-
include API
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def logging=(bool)
|
33
|
-
client.logging = bool
|
34
|
-
end
|
23
|
+
class ProtocolError < StandardError; end
|
24
|
+
class ServerDownError < StandardError; end
|
25
|
+
class BufferOverflowError < StandardError; end
|
26
|
+
class InvalidTypeError < StandardError; end
|
27
|
+
class ConnectionError < StandardError; end
|
28
|
+
class MessageError < StandardError; end
|
35
29
|
|
36
|
-
|
37
|
-
client.logging
|
38
|
-
end
|
39
|
-
|
40
|
-
def start
|
41
|
-
client.start_session
|
42
|
-
end
|
43
|
-
|
44
|
-
def status
|
45
|
-
client.status
|
46
|
-
end
|
30
|
+
VERSION = '0.3.0'
|
47
31
|
|
48
|
-
|
49
|
-
client.exchanges[name] ||= API::Exchange.new(client, name, opts)
|
50
|
-
end
|
51
|
-
|
52
|
-
def queue(name, opts = {})
|
53
|
-
client.queues[name] ||= API::Queue.new(client, name, opts)
|
54
|
-
end
|
55
|
-
|
56
|
-
def stop
|
57
|
-
client.close
|
58
|
-
end
|
59
|
-
|
60
|
-
def queues
|
61
|
-
client.queues ||= {}
|
62
|
-
end
|
32
|
+
# Returns the Bunny version number
|
63
33
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def host
|
69
|
-
client.host
|
70
|
-
end
|
71
|
-
|
72
|
-
def vhost
|
73
|
-
client.vhost
|
74
|
-
end
|
75
|
-
|
76
|
-
def port
|
77
|
-
client.port
|
34
|
+
def self.version
|
35
|
+
VERSION
|
78
36
|
end
|
79
|
-
|
37
|
+
|
80
38
|
end
|