bunny 0.4.4 → 0.5.1
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/Rakefile +21 -3
- data/bunny.gemspec +34 -20
- data/examples/{simple.rb → simple_08.rb} +0 -0
- data/examples/simple_09.rb +30 -0
- data/examples/{simple_ack.rb → simple_ack_08.rb} +0 -0
- data/examples/simple_ack_09.rb +33 -0
- data/examples/{simple_consumer.rb → simple_consumer_08.rb} +0 -0
- data/examples/simple_consumer_09.rb +55 -0
- data/examples/{simple_fanout.rb → simple_fanout_08.rb} +0 -0
- data/examples/simple_fanout_09.rb +39 -0
- data/examples/{simple_headers.rb → simple_headers_08.rb} +0 -0
- data/examples/simple_headers_09.rb +40 -0
- data/examples/{simple_publisher.rb → simple_publisher_08.rb} +0 -0
- data/examples/simple_publisher_09.rb +27 -0
- data/examples/{simple_topic.rb → simple_topic_08.rb} +0 -0
- data/examples/simple_topic_09.rb +59 -0
- data/lib/bunny.rb +19 -14
- data/lib/bunny/channel08.rb +38 -0
- data/lib/bunny/channel09.rb +38 -0
- data/lib/bunny/client08.rb +167 -74
- data/lib/bunny/{client091.rb → client09.rb} +195 -92
- data/lib/bunny/{exchange091.rb → exchange09.rb} +12 -11
- data/lib/bunny/queue08.rb +1 -0
- data/lib/bunny/{queue091.rb → queue09.rb} +38 -28
- data/lib/qrack/client.rb +7 -0
- data/lib/qrack/protocol/{protocol.rb → protocol08.rb} +1 -4
- data/lib/qrack/protocol/protocol09.rb +133 -0
- data/lib/qrack/protocol/{spec091.rb → spec09.rb} +5 -5
- data/lib/qrack/qrack08.rb +2 -10
- data/lib/qrack/qrack09.rb +20 -0
- data/lib/qrack/transport/{buffer.rb → buffer08.rb} +0 -0
- data/lib/qrack/transport/buffer09.rb +276 -0
- data/lib/qrack/transport/{frame091.rb → frame09.rb} +8 -8
- data/spec/{bunny_spec.rb → spec_08/bunny_spec.rb} +4 -4
- data/spec/{exchange_spec.rb → spec_08/exchange_spec.rb} +3 -10
- data/spec/{queue_spec.rb → spec_08/queue_spec.rb} +1 -1
- data/spec/spec_09/bunny_spec.rb +40 -0
- data/spec/spec_09/exchange_spec.rb +131 -0
- data/spec/spec_09/queue_spec.rb +106 -0
- metadata +38 -22
- data/lib/qrack/qrack091.rb +0 -28
data/lib/qrack/qrack08.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
$: << File.expand_path(File.dirname(__FILE__))
|
2
2
|
|
3
3
|
require 'protocol/spec08'
|
4
|
-
require 'protocol/
|
4
|
+
require 'protocol/protocol08'
|
5
5
|
|
6
|
-
require 'transport/
|
6
|
+
require 'transport/buffer08'
|
7
7
|
require 'transport/frame08'
|
8
8
|
|
9
9
|
require 'qrack/client'
|
@@ -17,12 +17,4 @@ module Qrack
|
|
17
17
|
class BufferOverflowError < StandardError; end
|
18
18
|
class InvalidTypeError < StandardError; end
|
19
19
|
|
20
|
-
# Qrack version number
|
21
|
-
VERSION = '0.0.1'
|
22
|
-
|
23
|
-
# Return the Qrack version
|
24
|
-
def self.version
|
25
|
-
VERSION
|
26
|
-
end
|
27
|
-
|
28
20
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'protocol/spec09'
|
4
|
+
require 'protocol/protocol09'
|
5
|
+
|
6
|
+
require 'transport/buffer09'
|
7
|
+
require 'transport/frame09'
|
8
|
+
|
9
|
+
require 'qrack/client'
|
10
|
+
|
11
|
+
module Qrack
|
12
|
+
|
13
|
+
include Protocol09
|
14
|
+
include Transport09
|
15
|
+
|
16
|
+
# Errors
|
17
|
+
class BufferOverflowError < StandardError; end
|
18
|
+
class InvalidTypeError < StandardError; end
|
19
|
+
|
20
|
+
end
|
File without changes
|
@@ -0,0 +1,276 @@
|
|
1
|
+
if [].map.respond_to? :with_index
|
2
|
+
class Array #:nodoc:
|
3
|
+
def enum_with_index
|
4
|
+
each.with_index
|
5
|
+
end
|
6
|
+
end
|
7
|
+
else
|
8
|
+
require 'enumerator'
|
9
|
+
end
|
10
|
+
|
11
|
+
module Qrack
|
12
|
+
module Transport09 #:nodoc: all
|
13
|
+
class Buffer
|
14
|
+
|
15
|
+
def initialize data = ''
|
16
|
+
@data = data
|
17
|
+
@pos = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :pos
|
21
|
+
|
22
|
+
def data
|
23
|
+
@data.clone
|
24
|
+
end
|
25
|
+
alias :contents :data
|
26
|
+
alias :to_s :data
|
27
|
+
|
28
|
+
def << data
|
29
|
+
@data << data.to_s
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def length
|
34
|
+
@data.length
|
35
|
+
end
|
36
|
+
|
37
|
+
def empty?
|
38
|
+
pos == length
|
39
|
+
end
|
40
|
+
|
41
|
+
def rewind
|
42
|
+
@pos = 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def read_properties *types
|
46
|
+
types.shift if types.first == :properties
|
47
|
+
|
48
|
+
i = 0
|
49
|
+
values = []
|
50
|
+
|
51
|
+
while props = read(:short)
|
52
|
+
(0..14).each do |n|
|
53
|
+
# no more property types
|
54
|
+
break unless types[i]
|
55
|
+
|
56
|
+
# if flag is set
|
57
|
+
if props & (1<<(15-n)) != 0
|
58
|
+
if types[i] == :bit
|
59
|
+
# bit values exist in flags only
|
60
|
+
values << true
|
61
|
+
else
|
62
|
+
# save type name for later reading
|
63
|
+
values << types[i]
|
64
|
+
end
|
65
|
+
else
|
66
|
+
# property not set or is false bit
|
67
|
+
values << (types[i] == :bit ? false : nil)
|
68
|
+
end
|
69
|
+
|
70
|
+
i+=1
|
71
|
+
end
|
72
|
+
|
73
|
+
# bit(0) == 0 means no more property flags
|
74
|
+
break unless props & 1 == 1
|
75
|
+
end
|
76
|
+
|
77
|
+
values.map do |value|
|
78
|
+
value.is_a?(Symbol) ? read(value) : value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def read *types
|
83
|
+
if types.first == :properties
|
84
|
+
return read_properties(*types)
|
85
|
+
end
|
86
|
+
|
87
|
+
values = types.map do |type|
|
88
|
+
case type
|
89
|
+
when :octet
|
90
|
+
_read(1, 'C')
|
91
|
+
when :short
|
92
|
+
_read(2, 'n')
|
93
|
+
when :long
|
94
|
+
_read(4, 'N')
|
95
|
+
when :longlong
|
96
|
+
upper, lower = _read(8, 'NN')
|
97
|
+
upper << 32 | lower
|
98
|
+
when :shortstr
|
99
|
+
_read read(:octet)
|
100
|
+
when :longstr
|
101
|
+
_read read(:long)
|
102
|
+
when :timestamp
|
103
|
+
Time.at read(:longlong)
|
104
|
+
when :table
|
105
|
+
t = Hash.new
|
106
|
+
|
107
|
+
table = Buffer.new(read(:longstr))
|
108
|
+
until table.empty?
|
109
|
+
key, type = table.read(:shortstr, :octet)
|
110
|
+
key = key.intern
|
111
|
+
t[key] ||= case type
|
112
|
+
when 83 # 'S'
|
113
|
+
table.read(:longstr)
|
114
|
+
when 73 # 'I'
|
115
|
+
table.read(:long)
|
116
|
+
when 68 # 'D'
|
117
|
+
exp = table.read(:octet)
|
118
|
+
num = table.read(:long)
|
119
|
+
num / 10.0**exp
|
120
|
+
when 84 # 'T'
|
121
|
+
table.read(:timestamp)
|
122
|
+
when 70 # 'F'
|
123
|
+
table.read(:table)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
t
|
128
|
+
when :bit
|
129
|
+
if (@bits ||= []).empty?
|
130
|
+
val = read(:octet)
|
131
|
+
@bits = (0..7).map{|i| (val & 1<<i) != 0 }
|
132
|
+
end
|
133
|
+
|
134
|
+
@bits.shift
|
135
|
+
else
|
136
|
+
raise Qrack::InvalidTypeError, "Cannot read data of type #{type}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
types.size == 1 ? values.first : values
|
141
|
+
end
|
142
|
+
|
143
|
+
def write type, data
|
144
|
+
case type
|
145
|
+
when :octet
|
146
|
+
_write(data, 'C')
|
147
|
+
when :short
|
148
|
+
_write(data, 'n')
|
149
|
+
when :long
|
150
|
+
_write(data, 'N')
|
151
|
+
when :longlong
|
152
|
+
lower = data & 0xffffffff
|
153
|
+
upper = (data & ~0xffffffff) >> 32
|
154
|
+
_write([upper, lower], 'NN')
|
155
|
+
when :shortstr
|
156
|
+
data = (data || '').to_s
|
157
|
+
_write([data.length, data], 'Ca*')
|
158
|
+
when :longstr
|
159
|
+
if data.is_a? Hash
|
160
|
+
write(:table, data)
|
161
|
+
else
|
162
|
+
data = (data || '').to_s
|
163
|
+
_write([data.length, data], 'Na*')
|
164
|
+
end
|
165
|
+
when :timestamp
|
166
|
+
write(:longlong, data.to_i)
|
167
|
+
when :table
|
168
|
+
data ||= {}
|
169
|
+
write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
|
170
|
+
table.write(:shortstr, key.to_s)
|
171
|
+
|
172
|
+
case value
|
173
|
+
when String
|
174
|
+
table.write(:octet, 83) # 'S'
|
175
|
+
table.write(:longstr, value.to_s)
|
176
|
+
when Fixnum
|
177
|
+
table.write(:octet, 73) # 'I'
|
178
|
+
table.write(:long, value)
|
179
|
+
when Float
|
180
|
+
table.write(:octet, 68) # 'D'
|
181
|
+
# XXX there's gotta be a better way to do this..
|
182
|
+
exp = value.to_s.split('.').last.length
|
183
|
+
num = value * 10**exp
|
184
|
+
table.write(:octet, exp)
|
185
|
+
table.write(:long, num)
|
186
|
+
when Time
|
187
|
+
table.write(:octet, 84) # 'T'
|
188
|
+
table.write(:timestamp, value)
|
189
|
+
when Hash
|
190
|
+
table.write(:octet, 70) # 'F'
|
191
|
+
table.write(:table, value)
|
192
|
+
end
|
193
|
+
|
194
|
+
table
|
195
|
+
end)
|
196
|
+
when :bit
|
197
|
+
[*data].to_enum(:each_slice, 8).each{|bits|
|
198
|
+
write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
|
199
|
+
byte |= 1<<i if bit
|
200
|
+
byte
|
201
|
+
})
|
202
|
+
}
|
203
|
+
when :properties
|
204
|
+
values = []
|
205
|
+
data.enum_with_index.inject(0) do |short, ((type, value), i)|
|
206
|
+
n = i % 15
|
207
|
+
last = i+1 == data.size
|
208
|
+
|
209
|
+
if (n == 0 and i != 0) or last
|
210
|
+
if data.size > i+1
|
211
|
+
short |= 1<<0
|
212
|
+
elsif last and value
|
213
|
+
values << [type,value]
|
214
|
+
short |= 1<<(15-n)
|
215
|
+
end
|
216
|
+
|
217
|
+
write(:short, short)
|
218
|
+
short = 0
|
219
|
+
end
|
220
|
+
|
221
|
+
if value and !last
|
222
|
+
values << [type,value]
|
223
|
+
short |= 1<<(15-n)
|
224
|
+
end
|
225
|
+
|
226
|
+
short
|
227
|
+
end
|
228
|
+
|
229
|
+
values.each do |type, value|
|
230
|
+
write(type, value) unless type == :bit
|
231
|
+
end
|
232
|
+
else
|
233
|
+
raise Qrack::InvalidTypeError, "Cannot write data of type #{type}"
|
234
|
+
end
|
235
|
+
|
236
|
+
self
|
237
|
+
end
|
238
|
+
|
239
|
+
def extract
|
240
|
+
begin
|
241
|
+
cur_data, cur_pos = @data.clone, @pos
|
242
|
+
yield self
|
243
|
+
rescue Qrack::BufferOverflowError
|
244
|
+
@data, @pos = cur_data, cur_pos
|
245
|
+
nil
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def _read(size, pack = nil)
|
250
|
+
if @data.is_a?(Qrack::Client)
|
251
|
+
raw = @data.read(size)
|
252
|
+
return raw if raw.nil? or pack.nil?
|
253
|
+
return raw.unpack(pack).first
|
254
|
+
end
|
255
|
+
|
256
|
+
if @pos + size > length
|
257
|
+
raise Qrack::BufferOverflowError
|
258
|
+
else
|
259
|
+
data = @data[@pos,size]
|
260
|
+
@data[@pos,size] = ''
|
261
|
+
if pack
|
262
|
+
data = data.unpack(pack)
|
263
|
+
data = data.pop if data.size == 1
|
264
|
+
end
|
265
|
+
data
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def _write data, pack = nil
|
270
|
+
data = [*data].pack(pack) if pack
|
271
|
+
@data[@pos,0] = data
|
272
|
+
@pos += data.length
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# DO NOT EDIT! (edit ext/qparser.rb and config.yml instead, and run 'ruby qparser.rb')
|
6
6
|
|
7
7
|
module Qrack
|
8
|
-
module
|
8
|
+
module Transport09
|
9
9
|
class Frame
|
10
10
|
|
11
11
|
FOOTER = 206
|
@@ -29,7 +29,7 @@ module Qrack
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def to_binary
|
32
|
-
buf =
|
32
|
+
buf = Transport09::Buffer.new
|
33
33
|
buf.write :octet, id
|
34
34
|
buf.write :short, channel
|
35
35
|
buf.write :longstr, payload
|
@@ -49,10 +49,10 @@ module Qrack
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def self.parse buf
|
52
|
-
buf =
|
52
|
+
buf = Transport09::Buffer.new(buf) unless buf.is_a? Transport09::Buffer
|
53
53
|
buf.extract do
|
54
54
|
id, channel, payload, footer = buf.read(:octet, :short, :longstr, :octet)
|
55
|
-
Qrack::
|
55
|
+
Qrack::Transport09.const_get(@types[id]).new(payload, channel) if footer == FOOTER
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -64,8 +64,8 @@ module Qrack
|
|
64
64
|
|
65
65
|
def initialize payload = nil, channel = 0
|
66
66
|
super
|
67
|
-
unless @payload.is_a?
|
68
|
-
@payload =
|
67
|
+
unless @payload.is_a? Protocol09::Class::Method or @payload.nil?
|
68
|
+
@payload = Protocol09.parse(@payload)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -76,8 +76,8 @@ module Qrack
|
|
76
76
|
|
77
77
|
def initialize payload = nil, channel = 0
|
78
78
|
super
|
79
|
-
unless @payload.is_a?
|
80
|
-
@payload =
|
79
|
+
unless @payload.is_a? Protocol09::Header or @payload.nil?
|
80
|
+
@payload = Protocol09::Header.new(@payload)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -6,15 +6,15 @@
|
|
6
6
|
# If this is not the case, please change the 'Bunny.new' call below to include
|
7
7
|
# the relevant arguments e.g. @b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
|
8
8
|
|
9
|
-
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib bunny]))
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. lib bunny]))
|
10
10
|
|
11
11
|
describe Bunny do
|
12
|
-
|
12
|
+
|
13
13
|
before(:each) do
|
14
14
|
@b = Bunny.new
|
15
15
|
@b.start
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
it "should connect to an AMQP server" do
|
19
19
|
@b.status.should == :connected
|
20
20
|
end
|
@@ -36,5 +36,5 @@ describe Bunny do
|
|
36
36
|
it "should be able to set QoS" do
|
37
37
|
@b.qos.should == :qos_ok
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
end
|
@@ -6,15 +6,15 @@
|
|
6
6
|
# If this is not the case, please change the 'Bunny.new' call below to include
|
7
7
|
# the relevant arguments e.g. @b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
|
8
8
|
|
9
|
-
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib bunny]))
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. lib bunny]))
|
10
10
|
|
11
11
|
describe Bunny do
|
12
|
-
|
12
|
+
|
13
13
|
before(:each) do
|
14
14
|
@b = Bunny.new
|
15
15
|
@b.start
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
it "should raise an error if instantiated as non-existent type" do
|
19
19
|
lambda { @b.exchange('bogus_ex', :type => :bogus) }.should raise_error(Bunny::ProtocolError)
|
20
20
|
end
|
@@ -51,9 +51,6 @@ describe Bunny do
|
|
51
51
|
@b.exchanges.has_key?('amq.topic').should be true
|
52
52
|
end
|
53
53
|
|
54
|
-
|
55
|
-
=begin
|
56
|
-
#*** Uncomment these tests if your broker/server supports headers exchanges ***
|
57
54
|
it "should allow a default headers (amq.match) exchange to be instantiated without specifying :type" do
|
58
55
|
exch = @b.exchange('amq.match')
|
59
56
|
exch.should be_an_instance_of Bunny::Exchange
|
@@ -69,7 +66,6 @@ describe Bunny do
|
|
69
66
|
exch.type.should == :headers
|
70
67
|
@b.exchanges.has_key?('amq.headers').should be true
|
71
68
|
end
|
72
|
-
=end
|
73
69
|
|
74
70
|
it "should create an exchange as direct by default" do
|
75
71
|
exch = @b.exchange('direct_defaultex')
|
@@ -103,8 +99,6 @@ describe Bunny do
|
|
103
99
|
@b.exchanges.has_key?('fanout_exchange').should be true
|
104
100
|
end
|
105
101
|
|
106
|
-
=begin
|
107
|
-
#*** Uncomment this test if your broker/server supports headers exchanges ***
|
108
102
|
it "should be able to be instantiated as a headers exchange" do
|
109
103
|
exch = @b.exchange('headers_exchange', :type => :headers)
|
110
104
|
exch.should be_an_instance_of Bunny::Exchange
|
@@ -112,7 +106,6 @@ describe Bunny do
|
|
112
106
|
exch.type.should == :headers
|
113
107
|
@b.exchanges.has_key?('headers_exchange').should be true
|
114
108
|
end
|
115
|
-
=end
|
116
109
|
|
117
110
|
it "should ignore the :nowait option when instantiated" do
|
118
111
|
exch = @b.exchange('direct2_exchange', :nowait => true)
|