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/protocol/amqp-0.8.json
CHANGED
data/protocol/codegen.rb
CHANGED
@@ -18,13 +18,8 @@ puts ERB.new(%q[
|
|
18
18
|
#
|
19
19
|
# DO NOT EDIT! (edit protocol/codegen.rb instead, and run `rake codegen`)
|
20
20
|
|
21
|
-
module
|
22
|
-
|
23
|
-
VERSION_MAJOR = <%= s['major-version'] %>
|
24
|
-
VERSION_MINOR = <%= s['minor-version'] %>
|
25
|
-
PORT = <%= s['port'] %>
|
26
|
-
|
27
|
-
class Frame
|
21
|
+
module Transport
|
22
|
+
class Frame
|
28
23
|
def self.types
|
29
24
|
@types ||= {}
|
30
25
|
end
|
@@ -46,6 +41,13 @@ puts ERB.new(%q[
|
|
46
41
|
|
47
42
|
FOOTER = <%= frame_end = s['constants'].find{|c| c['name'] == 'FRAME-END' }['value'] %>
|
48
43
|
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module Protocol
|
47
|
+
HEADER = <%= s['name'].dump %>.freeze
|
48
|
+
VERSION_MAJOR = <%= s['major-version'] %>
|
49
|
+
VERSION_MINOR = <%= s['minor-version'] %>
|
50
|
+
PORT = <%= s['port'] %>
|
49
51
|
|
50
52
|
RESPONSES = {
|
51
53
|
<%- s['constants'].select{|c| c['value'] != frame_end and (200..500).include? c['value'] }.each do |c| -%>
|
@@ -59,115 +61,111 @@ puts ERB.new(%q[
|
|
59
61
|
<%- end -%>
|
60
62
|
]
|
61
63
|
|
62
|
-
|
63
|
-
class
|
64
|
+
class Class
|
65
|
+
class << self
|
66
|
+
FIELDS.each do |f|
|
67
|
+
class_eval %[
|
68
|
+
def #{f} name
|
69
|
+
properties << [ :#{f}, name ] unless properties.include?([:#{f}, name])
|
70
|
+
attr_accessor name
|
71
|
+
end
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
def properties() @properties ||= [] end
|
76
|
+
|
77
|
+
def id() self::ID end
|
78
|
+
def name() self::NAME end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Method
|
64
82
|
class << self
|
65
83
|
FIELDS.each do |f|
|
66
84
|
class_eval %[
|
67
85
|
def #{f} name
|
68
|
-
|
86
|
+
arguments << [ :#{f}, name ] unless arguments.include?([:#{f}, name])
|
69
87
|
attr_accessor name
|
70
88
|
end
|
71
89
|
]
|
72
90
|
end
|
73
91
|
|
74
|
-
def
|
92
|
+
def arguments() @arguments ||= [] end
|
75
93
|
|
76
|
-
def
|
77
|
-
def
|
94
|
+
def parent() Protocol.const_get(self.to_s[/Protocol::(.+?)::/,1]) end
|
95
|
+
def id() self::ID end
|
96
|
+
def name() self::NAME end
|
78
97
|
end
|
79
98
|
|
80
|
-
|
81
|
-
class
|
82
|
-
|
83
|
-
class_eval %[
|
84
|
-
def #{f} name
|
85
|
-
arguments << [ :#{f}, name ] unless arguments.include?([:#{f}, name])
|
86
|
-
attr_accessor name
|
87
|
-
end
|
88
|
-
]
|
89
|
-
end
|
90
|
-
|
91
|
-
def arguments() @arguments ||= [] end
|
92
|
-
|
93
|
-
def parent() Protocol.const_get(self.to_s[/Protocol::(.+?)::/,1]) end
|
94
|
-
def id() self::ID end
|
95
|
-
def name() self::NAME end
|
96
|
-
end
|
97
|
-
|
98
|
-
def == b
|
99
|
-
self.class.arguments.inject(true) do |eql, (type, name)|
|
100
|
-
eql and __send__("#{name}") == b.__send__("#{name}")
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.methods() @methods ||= {} end
|
106
|
-
|
107
|
-
def self.Method(id, name)
|
108
|
-
@_base_methods ||= {}
|
109
|
-
@_base_methods[id] ||= ::Class.new(Method) do
|
110
|
-
class_eval %[
|
111
|
-
def self.inherited klass
|
112
|
-
klass.const_set(:ID, #{id})
|
113
|
-
klass.const_set(:NAME, :#{name.to_s})
|
114
|
-
klass.parent.methods[#{id}] = klass
|
115
|
-
klass.parent.methods[klass::NAME] = klass
|
116
|
-
end
|
117
|
-
]
|
99
|
+
def == b
|
100
|
+
self.class.arguments.inject(true) do |eql, (type, name)|
|
101
|
+
eql and __send__("#{name}") == b.__send__("#{name}")
|
118
102
|
end
|
119
103
|
end
|
120
104
|
end
|
121
|
-
|
122
|
-
def self.
|
123
|
-
|
124
|
-
def self.
|
125
|
-
@
|
126
|
-
@
|
105
|
+
|
106
|
+
def self.methods() @methods ||= {} end
|
107
|
+
|
108
|
+
def self.Method(id, name)
|
109
|
+
@_base_methods ||= {}
|
110
|
+
@_base_methods[id] ||= ::Class.new(Method) do
|
127
111
|
class_eval %[
|
128
112
|
def self.inherited klass
|
129
113
|
klass.const_set(:ID, #{id})
|
130
114
|
klass.const_set(:NAME, :#{name.to_s})
|
131
|
-
|
132
|
-
|
115
|
+
klass.parent.methods[#{id}] = klass
|
116
|
+
klass.parent.methods[klass::NAME] = klass
|
133
117
|
end
|
134
118
|
]
|
135
119
|
end
|
136
120
|
end
|
137
121
|
end
|
122
|
+
|
123
|
+
def self.classes() @classes ||= {} end
|
124
|
+
|
125
|
+
def self.Class(id, name)
|
126
|
+
@_base_classes ||= {}
|
127
|
+
@_base_classes[id] ||= ::Class.new(Class) do
|
128
|
+
class_eval %[
|
129
|
+
def self.inherited klass
|
130
|
+
klass.const_set(:ID, #{id})
|
131
|
+
klass.const_set(:NAME, :#{name.to_s})
|
132
|
+
Protocol.classes[#{id}] = klass
|
133
|
+
Protocol.classes[klass::NAME] = klass
|
134
|
+
end
|
135
|
+
]
|
136
|
+
end
|
137
|
+
end
|
138
138
|
end
|
139
139
|
|
140
|
-
module
|
141
|
-
|
142
|
-
|
143
|
-
|
140
|
+
module Protocol
|
141
|
+
<%- s['classes'].each do |c| -%>
|
142
|
+
class <%= c['name'].capitalize.ljust(12) %> < Class( <%= c['id'].to_s.rjust(3) %>, :<%= c['name'].ljust(12) %> ); end
|
143
|
+
<%- end -%>
|
144
|
+
|
145
|
+
<%- s['classes'].each do |c| -%>
|
146
|
+
class <%= c['name'].capitalize %>
|
147
|
+
<%- c['properties'].each do |p| -%>
|
148
|
+
<%= p['type'].ljust(10) %> :<%= p['name'].tr('-','_') %>
|
149
|
+
<%- end if c['properties'] -%>
|
150
|
+
|
151
|
+
<%- c['methods'].each do |m| -%>
|
152
|
+
class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"}.ljust(12) %> < Method( <%= m['id'].to_s.rjust(3) %>, :<%= m['name'].tr('- ','_').ljust(14) %> ); end
|
144
153
|
<%- end -%>
|
145
154
|
|
146
|
-
<%-
|
147
|
-
class <%=
|
148
|
-
<%-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"}.ljust(12) %> < Method( <%= m['id'].to_s.rjust(3) %>, :<%= m['name'].tr('- ','_').ljust(14) %> ); end
|
154
|
-
<%- end -%>
|
155
|
-
|
156
|
-
<%- c['methods'].each do |m| -%>
|
157
|
-
class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"} %>
|
158
|
-
<%- m['arguments'].each do |a| -%>
|
159
|
-
<%- if a['domain'] -%>
|
160
|
-
<%= s['domains'].find{|k,v| k == a['domain']}.last.ljust(10) %> :<%= a['name'].tr('- ','_') %>
|
161
|
-
<%- else -%>
|
162
|
-
<%= a['type'].ljust(10) %> :<%= a['name'].tr('- ','_') %>
|
163
|
-
<%- end -%>
|
164
|
-
<%- end if m['arguments'] -%>
|
165
|
-
end
|
166
|
-
|
155
|
+
<%- c['methods'].each do |m| -%>
|
156
|
+
class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"} %>
|
157
|
+
<%- m['arguments'].each do |a| -%>
|
158
|
+
<%- if a['domain'] -%>
|
159
|
+
<%= s['domains'].find{|k,v| k == a['domain']}.last.ljust(10) %> :<%= a['name'].tr('- ','_') %>
|
160
|
+
<%- else -%>
|
161
|
+
<%= a['type'].ljust(10) %> :<%= a['name'].tr('- ','_') %>
|
167
162
|
<%- end -%>
|
163
|
+
<%- end if m['arguments'] -%>
|
168
164
|
end
|
169
165
|
|
170
166
|
<%- end -%>
|
171
167
|
end
|
168
|
+
|
169
|
+
<%- end -%>
|
172
170
|
end
|
173
|
-
].gsub!(/^ /,''), nil, '>-%').result(binding)
|
171
|
+
].gsub!(/^ /,''), nil, '>-%').result(binding)
|
data/spec/exchange_spec.rb
CHANGED
@@ -16,10 +16,52 @@ describe Bunny::Exchange do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should raise an error if instantiated as non-existent type" do
|
19
|
-
lambda { @b.exchange('bogus_ex', :type => :bogus) }.should raise_error(
|
19
|
+
lambda { @b.exchange('bogus_ex', :type => :bogus) }.should raise_error(API::ProtocolError)
|
20
20
|
end
|
21
21
|
|
22
|
-
it "should
|
22
|
+
it "should allow a default direct exchange to be instantiated by specifying :type" do
|
23
|
+
exch = @b.exchange('amq.direct', :type => :direct)
|
24
|
+
exch.should be_an_instance_of Bunny::Exchange
|
25
|
+
exch.name.should == 'amq.direct'
|
26
|
+
exch.type.should == :direct
|
27
|
+
@b.exchanges.has_key?('amq.direct').should be true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should allow a default direct exchange to be instantiated without specifying :type" do
|
31
|
+
exch = @b.exchange('amq.direct')
|
32
|
+
exch.should be_an_instance_of Bunny::Exchange
|
33
|
+
exch.name.should == 'amq.direct'
|
34
|
+
exch.type.should == :direct
|
35
|
+
@b.exchanges.has_key?('amq.direct').should be true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should allow a default fanout exchange to be instantiated without specifying :type" do
|
39
|
+
exch = @b.exchange('amq.fanout')
|
40
|
+
exch.should be_an_instance_of Bunny::Exchange
|
41
|
+
exch.name.should == 'amq.fanout'
|
42
|
+
exch.type.should == :fanout
|
43
|
+
@b.exchanges.has_key?('amq.fanout').should be true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should allow a default topic exchange to be instantiated without specifying :type" do
|
47
|
+
exch = @b.exchange('amq.topic')
|
48
|
+
exch.should be_an_instance_of Bunny::Exchange
|
49
|
+
exch.name.should == 'amq.topic'
|
50
|
+
exch.type.should == :topic
|
51
|
+
@b.exchanges.has_key?('amq.topic').should be true
|
52
|
+
end
|
53
|
+
|
54
|
+
# headers exchange not implemented in RabbitMQ yet. Uncomment if target broker/server supports it
|
55
|
+
#
|
56
|
+
#it "should allow a default headers exchange to be instantiated without specifying :type" do
|
57
|
+
# exch = @b.exchange('amq.match')
|
58
|
+
# exch.should be_an_instance_of Bunny::Exchange
|
59
|
+
# exch.name.should == 'amq.match'
|
60
|
+
# exch.type.should == :headers
|
61
|
+
# @b.exchanges.has_key?('amq.match').should be true
|
62
|
+
#end
|
63
|
+
|
64
|
+
it "should create an exchange as direct by default" do
|
23
65
|
exch = @b.exchange('direct_defaultex')
|
24
66
|
exch.should be_an_instance_of Bunny::Exchange
|
25
67
|
exch.name.should == 'direct_defaultex'
|
data/spec/queue_spec.rb
CHANGED
@@ -53,7 +53,7 @@ describe Bunny::Queue do
|
|
53
53
|
q = @b.queue('test1')
|
54
54
|
msg = q.pop(:header => true)
|
55
55
|
msg.should be_an_instance_of Hash
|
56
|
-
msg[:header].should be_an_instance_of
|
56
|
+
msg[:header].should be_an_instance_of Protocol::Header
|
57
57
|
msg[:payload].should == 'This is a test message'
|
58
58
|
q.message_count.should == 0
|
59
59
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bunny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Duncan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-05-01 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -24,27 +24,26 @@ extra_rdoc_files: []
|
|
24
24
|
files:
|
25
25
|
- Rakefile
|
26
26
|
- README.markdown
|
27
|
-
- lib/
|
28
|
-
- lib/
|
29
|
-
- lib/
|
27
|
+
- lib/api_messages.rb
|
28
|
+
- lib/bunny.rb
|
29
|
+
- lib/engineroom/buffer.rb
|
30
|
+
- lib/engineroom/frame.rb
|
31
|
+
- lib/engineroom/protocol.rb
|
32
|
+
- lib/engineroom/spec.rb
|
30
33
|
- lib/bunny/exchange.rb
|
31
|
-
- lib/amqp/frame.rb
|
32
34
|
- lib/bunny/header.rb
|
33
|
-
- lib/amqp/protocol.rb
|
34
35
|
- lib/bunny/queue.rb
|
35
|
-
- lib/
|
36
|
-
- lib/amqp/spec.rb
|
37
|
-
- lib/bunny.rb
|
36
|
+
- lib/bunny/client.rb
|
38
37
|
- examples/simple.rb
|
39
|
-
- examples/
|
38
|
+
- examples/simple_fanout.rb
|
40
39
|
- examples/simple_consumer.rb
|
41
40
|
- examples/simple_publisher.rb
|
42
41
|
- examples/simple_ack.rb
|
42
|
+
- examples/simple_topic.rb
|
43
43
|
- spec/bunny_spec.rb
|
44
44
|
- spec/exchange_spec.rb
|
45
45
|
- spec/queue_spec.rb
|
46
46
|
- protocol/amqp-0.8.json
|
47
|
-
- protocol/amqp-0.8.xml
|
48
47
|
- protocol/codegen.rb
|
49
48
|
has_rdoc: true
|
50
49
|
homepage: http://github.com/celldee/bunny
|
data/lib/amqp/protocol.rb
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
module AMQP
|
2
|
-
module Protocol
|
3
|
-
#:stopdoc:
|
4
|
-
class Class::Method
|
5
|
-
def initialize *args
|
6
|
-
opts = args.pop if args.last.is_a? Hash
|
7
|
-
opts ||= {}
|
8
|
-
|
9
|
-
@debug = 1 # XXX hack, p(obj) == '' if no instance vars are set
|
10
|
-
|
11
|
-
if args.size == 1 and args.first.is_a? Buffer
|
12
|
-
buf = args.shift
|
13
|
-
else
|
14
|
-
buf = nil
|
15
|
-
end
|
16
|
-
|
17
|
-
self.class.arguments.each do |type, name|
|
18
|
-
val = buf ? buf.read(type) :
|
19
|
-
args.shift || opts[name] || opts[name.to_s]
|
20
|
-
instance_variable_set("@#{name}", val)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def arguments
|
25
|
-
self.class.arguments.inject({}) do |hash, (type, name)|
|
26
|
-
hash.update name => instance_variable_get("@#{name}")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_binary
|
31
|
-
buf = Buffer.new
|
32
|
-
buf.write :short, self.class.parent.id
|
33
|
-
buf.write :short, self.class.id
|
34
|
-
|
35
|
-
bits = []
|
36
|
-
|
37
|
-
self.class.arguments.each do |type, name|
|
38
|
-
val = instance_variable_get("@#{name}")
|
39
|
-
if type == :bit
|
40
|
-
bits << (val || false)
|
41
|
-
else
|
42
|
-
unless bits.empty?
|
43
|
-
buf.write :bit, bits
|
44
|
-
bits = []
|
45
|
-
end
|
46
|
-
buf.write type, val
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
buf.write :bit, bits unless bits.empty?
|
51
|
-
buf.rewind
|
52
|
-
|
53
|
-
buf
|
54
|
-
end
|
55
|
-
|
56
|
-
def to_s
|
57
|
-
to_binary.to_s
|
58
|
-
end
|
59
|
-
|
60
|
-
def to_frame channel = 0
|
61
|
-
Frame::Method.new(self, channel)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
#:startdoc:
|
66
|
-
#
|
67
|
-
# Contains a properties hash that holds some potentially interesting
|
68
|
-
# information.
|
69
|
-
# * :delivery_mode
|
70
|
-
# 1 equals transient.
|
71
|
-
# 2 equals persistent. Unconsumed persistent messages will survive
|
72
|
-
# a server restart when they are stored in a durable queue.
|
73
|
-
# * :redelivered
|
74
|
-
# True or False
|
75
|
-
# * :routing_key
|
76
|
-
# The routing string used for matching this message to this queue.
|
77
|
-
# * :priority
|
78
|
-
# An integer in the range of 0 to 9 inclusive.
|
79
|
-
# * :content_type
|
80
|
-
# Always "application/octet-stream" (byte stream)
|
81
|
-
# * :exchange
|
82
|
-
# The source exchange which published this message.
|
83
|
-
# * :message_count
|
84
|
-
# The number of unconsumed messages contained in the queue.
|
85
|
-
# * :delivery_tag
|
86
|
-
# A monotonically increasing integer. This number should not be trusted
|
87
|
-
# as a sequence number. There is no guarantee it won't get reset.
|
88
|
-
class Header
|
89
|
-
def initialize *args
|
90
|
-
opts = args.pop if args.last.is_a? Hash
|
91
|
-
opts ||= {}
|
92
|
-
|
93
|
-
first = args.shift
|
94
|
-
|
95
|
-
if first.is_a? ::Class and first.ancestors.include? Protocol::Class
|
96
|
-
@klass = first
|
97
|
-
@size = args.shift || 0
|
98
|
-
@weight = args.shift || 0
|
99
|
-
@properties = opts
|
100
|
-
|
101
|
-
elsif first.is_a? Buffer or first.is_a? String
|
102
|
-
buf = first
|
103
|
-
buf = Buffer.new(buf) unless buf.is_a? Buffer
|
104
|
-
|
105
|
-
@klass = Protocol.classes[buf.read(:short)]
|
106
|
-
@weight = buf.read(:short)
|
107
|
-
@size = buf.read(:longlong)
|
108
|
-
|
109
|
-
props = buf.read(:properties, *klass.properties.map{|type,_| type })
|
110
|
-
@properties = Hash[*klass.properties.map{|_,name| name }.zip(props).reject{|k,v| v.nil? }.flatten]
|
111
|
-
|
112
|
-
else
|
113
|
-
raise ArgumentError, 'Invalid argument'
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
attr_accessor :klass, :size, :weight, :properties
|
118
|
-
|
119
|
-
def to_binary
|
120
|
-
buf = Buffer.new
|
121
|
-
buf.write :short, klass.id
|
122
|
-
buf.write :short, weight # XXX rabbitmq only supports weight == 0
|
123
|
-
buf.write :longlong, size
|
124
|
-
buf.write :properties, (klass.properties.map do |type, name|
|
125
|
-
[ type, properties[name] || properties[name.to_s] ]
|
126
|
-
end)
|
127
|
-
buf.rewind
|
128
|
-
buf
|
129
|
-
end
|
130
|
-
|
131
|
-
def to_s
|
132
|
-
to_binary.to_s
|
133
|
-
end
|
134
|
-
|
135
|
-
def to_frame channel = 0
|
136
|
-
Frame::Header.new(self, channel)
|
137
|
-
end
|
138
|
-
|
139
|
-
def == header
|
140
|
-
[ :klass, :size, :weight, :properties ].inject(true) do |eql, field|
|
141
|
-
eql and __send__(field) == header.__send__(field)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def method_missing meth, *args, &blk
|
146
|
-
@properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] :
|
147
|
-
super
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def self.parse buf
|
152
|
-
buf = Buffer.new(buf) unless buf.is_a? Buffer
|
153
|
-
class_id, method_id = buf.read(:short, :short)
|
154
|
-
classes[class_id].methods[method_id].new(buf)
|
155
|
-
end
|
156
|
-
#:stopdoc:
|
157
|
-
end
|
158
|
-
end
|