bunny 0.7.12 → 0.8.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/.gitignore +2 -2
- data/.travis.yml +7 -16
- data/CHANGELOG +3 -21
- data/Gemfile +2 -4
- data/README.textile +31 -9
- data/Rakefile +3 -3
- data/bunny.gemspec +6 -3
- data/examples/{simple_08.rb → simple.rb} +1 -1
- data/examples/{simple_ack_08.rb → simple_ack.rb} +1 -1
- data/examples/{simple_consumer_08.rb → simple_consumer.rb} +4 -4
- data/examples/{simple_fanout_08.rb → simple_fanout.rb} +1 -1
- data/examples/{simple_headers_08.rb → simple_headers.rb} +2 -2
- data/examples/{simple_publisher_09.rb → simple_publisher.rb} +1 -1
- data/examples/{simple_topic_09.rb → simple_topic.rb} +2 -2
- data/ext/amqp-0.9.1.json +1 -0
- data/ext/config.yml +3 -3
- data/ext/qparser.rb +9 -52
- data/lib/bunny.rb +15 -33
- data/lib/bunny/{channel08.rb → channel.rb} +0 -0
- data/lib/bunny/{client09.rb → client.rb} +34 -46
- data/lib/bunny/{exchange09.rb → exchange.rb} +16 -15
- data/lib/bunny/{queue09.rb → queue.rb} +26 -23
- data/lib/bunny/{subscription09.rb → subscription.rb} +11 -6
- data/lib/bunny/version.rb +1 -1
- data/lib/qrack/client.rb +30 -21
- data/lib/qrack/protocol/{protocol08.rb → protocol.rb} +2 -1
- data/lib/qrack/protocol/{spec09.rb → spec.rb} +8 -7
- data/lib/qrack/{qrack08.rb → qrack.rb} +4 -4
- data/lib/qrack/subscription.rb +58 -9
- data/lib/qrack/transport/{buffer08.rb → buffer.rb} +8 -0
- data/lib/qrack/transport/{frame08.rb → frame.rb} +7 -22
- data/spec/spec_09/bunny_spec.rb +10 -8
- data/spec/spec_09/connection_spec.rb +8 -3
- data/spec/spec_09/exchange_spec.rb +22 -19
- data/spec/spec_09/queue_spec.rb +32 -18
- metadata +69 -76
- checksums.yaml +0 -7
- data/examples/simple_09.rb +0 -32
- data/examples/simple_ack_09.rb +0 -35
- data/examples/simple_consumer_09.rb +0 -55
- data/examples/simple_fanout_09.rb +0 -41
- data/examples/simple_headers_09.rb +0 -42
- data/examples/simple_publisher_08.rb +0 -29
- data/examples/simple_topic_08.rb +0 -61
- data/ext/amqp-0.8.json +0 -616
- data/lib/bunny/channel09.rb +0 -39
- data/lib/bunny/client08.rb +0 -480
- data/lib/bunny/exchange08.rb +0 -177
- data/lib/bunny/queue08.rb +0 -403
- data/lib/bunny/subscription08.rb +0 -87
- data/lib/qrack/protocol/protocol09.rb +0 -135
- data/lib/qrack/protocol/spec08.rb +0 -828
- data/lib/qrack/qrack09.rb +0 -20
- data/lib/qrack/transport/buffer09.rb +0 -305
- data/lib/qrack/transport/frame09.rb +0 -97
- data/spec/spec_08/bunny_spec.rb +0 -75
- data/spec/spec_08/connection_spec.rb +0 -24
- data/spec/spec_08/exchange_spec.rb +0 -170
- data/spec/spec_08/queue_spec.rb +0 -239
data/lib/qrack/qrack09.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path(File.dirname(__FILE__))
|
4
|
-
|
5
|
-
require 'protocol/spec09'
|
6
|
-
require 'protocol/protocol09'
|
7
|
-
|
8
|
-
require 'transport/buffer09'
|
9
|
-
require 'transport/frame09'
|
10
|
-
|
11
|
-
require 'qrack/client'
|
12
|
-
require 'qrack/channel'
|
13
|
-
require 'qrack/queue'
|
14
|
-
require 'bunny/consumer'
|
15
|
-
require 'qrack/errors'
|
16
|
-
|
17
|
-
module Qrack
|
18
|
-
include Protocol09
|
19
|
-
include Transport09
|
20
|
-
end
|
@@ -1,305 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
if [].map.respond_to? :with_index
|
4
|
-
class Array #:nodoc:
|
5
|
-
def enum_with_index
|
6
|
-
each.with_index
|
7
|
-
end
|
8
|
-
end
|
9
|
-
else
|
10
|
-
require 'enumerator'
|
11
|
-
end
|
12
|
-
|
13
|
-
module Qrack
|
14
|
-
module Transport09 #:nodoc: all
|
15
|
-
class Buffer
|
16
|
-
|
17
|
-
def initialize data = ''
|
18
|
-
@data = data
|
19
|
-
@pos = 0
|
20
|
-
end
|
21
|
-
|
22
|
-
attr_reader :pos
|
23
|
-
|
24
|
-
def data
|
25
|
-
@data.clone
|
26
|
-
end
|
27
|
-
alias :contents :data
|
28
|
-
alias :to_s :data
|
29
|
-
|
30
|
-
def << data
|
31
|
-
@data << data.to_s
|
32
|
-
self
|
33
|
-
end
|
34
|
-
|
35
|
-
def length
|
36
|
-
@data.bytesize
|
37
|
-
end
|
38
|
-
|
39
|
-
def empty?
|
40
|
-
pos == length
|
41
|
-
end
|
42
|
-
|
43
|
-
def rewind
|
44
|
-
@pos = 0
|
45
|
-
end
|
46
|
-
|
47
|
-
def read_properties *types
|
48
|
-
types.shift if types.first == :properties
|
49
|
-
|
50
|
-
i = 0
|
51
|
-
values = []
|
52
|
-
|
53
|
-
while props = read(:short)
|
54
|
-
(0..14).each do |n|
|
55
|
-
# no more property types
|
56
|
-
break unless types[i]
|
57
|
-
|
58
|
-
# if flag is set
|
59
|
-
if props & (1<<(15-n)) != 0
|
60
|
-
if types[i] == :bit
|
61
|
-
# bit values exist in flags only
|
62
|
-
values << true
|
63
|
-
else
|
64
|
-
# save type name for later reading
|
65
|
-
values << types[i]
|
66
|
-
end
|
67
|
-
else
|
68
|
-
# property not set or is false bit
|
69
|
-
values << (types[i] == :bit ? false : nil)
|
70
|
-
end
|
71
|
-
|
72
|
-
i+=1
|
73
|
-
end
|
74
|
-
|
75
|
-
# bit(0) == 0 means no more property flags
|
76
|
-
break unless props & 1 == 1
|
77
|
-
end
|
78
|
-
|
79
|
-
values.map do |value|
|
80
|
-
value.is_a?(Symbol) ? read(value) : value
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def read *types
|
85
|
-
if types.first == :properties
|
86
|
-
return read_properties(*types)
|
87
|
-
end
|
88
|
-
|
89
|
-
values = types.map do |type|
|
90
|
-
case type
|
91
|
-
when :octet
|
92
|
-
_read(1, 'C')
|
93
|
-
when :short
|
94
|
-
_read(2, 'n')
|
95
|
-
when :long
|
96
|
-
_read(4, 'N')
|
97
|
-
when :longlong
|
98
|
-
upper, lower = _read(8, 'NN')
|
99
|
-
upper << 32 | lower
|
100
|
-
when :shortstr
|
101
|
-
_read read(:octet)
|
102
|
-
when :longstr
|
103
|
-
_read read(:long)
|
104
|
-
when :timestamp
|
105
|
-
Time.at read(:longlong)
|
106
|
-
when :table
|
107
|
-
t = Hash.new
|
108
|
-
|
109
|
-
table = Buffer.new(read(:longstr))
|
110
|
-
until table.empty?
|
111
|
-
key, type = table.read(:shortstr, :octet)
|
112
|
-
key = key.intern
|
113
|
-
t[key] ||= case type
|
114
|
-
when 83 # 'S'
|
115
|
-
table.read(:longstr)
|
116
|
-
when 73 # 'I'
|
117
|
-
table.read(:long)
|
118
|
-
when 68 # 'D'
|
119
|
-
exp = table.read(:octet)
|
120
|
-
num = table.read(:long)
|
121
|
-
num / 10.0**exp
|
122
|
-
when 84 # 'T'
|
123
|
-
table.read(:timestamp)
|
124
|
-
when 70 # 'F'
|
125
|
-
table.read(:table)
|
126
|
-
when 65 # 'A'
|
127
|
-
table.read(:array)
|
128
|
-
when 108 # 'l'
|
129
|
-
table.read(:longlong)
|
130
|
-
when 116 # 't'
|
131
|
-
table.read(:octet) == 1
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
t
|
136
|
-
when :bit
|
137
|
-
if (@bits ||= []).empty?
|
138
|
-
val = read(:octet)
|
139
|
-
@bits = (0..7).map{|i| (val & (1 << i)) != 0 }
|
140
|
-
end
|
141
|
-
|
142
|
-
@bits.shift
|
143
|
-
when :array
|
144
|
-
a = Array.new
|
145
|
-
|
146
|
-
array = Buffer.new(read(:longstr))
|
147
|
-
until array.empty?
|
148
|
-
type = array.read(:octet)
|
149
|
-
a << case type
|
150
|
-
when 70 # 'F'
|
151
|
-
array.read(:table)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
a
|
156
|
-
else
|
157
|
-
raise Qrack::InvalidTypeError, "Cannot read data of type #{type}"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
types.size == 1 ? values.first : values
|
162
|
-
end
|
163
|
-
|
164
|
-
def write type, data
|
165
|
-
case type
|
166
|
-
when :octet
|
167
|
-
_write(data, 'C')
|
168
|
-
when :short
|
169
|
-
_write(data, 'n')
|
170
|
-
when :long
|
171
|
-
_write(data, 'N')
|
172
|
-
when :longlong
|
173
|
-
lower = data & 0xffffffff
|
174
|
-
upper = (data & ~0xffffffff) >> 32
|
175
|
-
_write([upper, lower], 'NN')
|
176
|
-
when :shortstr
|
177
|
-
data = (data || '').to_s
|
178
|
-
_write([data.bytesize, data], 'Ca*')
|
179
|
-
when :longstr
|
180
|
-
if data.is_a? Hash
|
181
|
-
write(:table, data)
|
182
|
-
else
|
183
|
-
data = (data || '').to_s
|
184
|
-
_write([data.bytesize, data], 'Na*')
|
185
|
-
end
|
186
|
-
when :timestamp
|
187
|
-
write(:longlong, data.to_i)
|
188
|
-
when :table
|
189
|
-
data ||= {}
|
190
|
-
write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
|
191
|
-
table.write(:shortstr, key.to_s)
|
192
|
-
|
193
|
-
case value
|
194
|
-
when String
|
195
|
-
table.write(:octet, 83) # 'S'
|
196
|
-
table.write(:longstr, value.to_s)
|
197
|
-
when Fixnum
|
198
|
-
table.write(:octet, 73) # 'I'
|
199
|
-
table.write(:long, value)
|
200
|
-
when Float
|
201
|
-
table.write(:octet, 68) # 'D'
|
202
|
-
# XXX there's gotta be a better way to do this..
|
203
|
-
exp = value.to_s.split('.').last.bytesize
|
204
|
-
num = value * 10**exp
|
205
|
-
table.write(:octet, exp)
|
206
|
-
table.write(:long, num)
|
207
|
-
when Time
|
208
|
-
table.write(:octet, 84) # 'T'
|
209
|
-
table.write(:timestamp, value)
|
210
|
-
when Hash
|
211
|
-
table.write(:octet, 70) # 'F'
|
212
|
-
table.write(:table, value)
|
213
|
-
when TrueClass
|
214
|
-
table.write(:octet, 116) # 't'
|
215
|
-
table.write(:octet, 1)
|
216
|
-
when FalseClass
|
217
|
-
table.write(:octet, 116) # 't'
|
218
|
-
table.write(:octet, 0)
|
219
|
-
else
|
220
|
-
raise Qrack::InvalidTypeError, "Cannot write table field for the type of #{value}"
|
221
|
-
end
|
222
|
-
|
223
|
-
table
|
224
|
-
end)
|
225
|
-
when :bit
|
226
|
-
[*data].to_enum(:each_slice, 8).each{|bits|
|
227
|
-
write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
|
228
|
-
byte |= (1 << i) if bit
|
229
|
-
byte
|
230
|
-
})
|
231
|
-
}
|
232
|
-
when :properties
|
233
|
-
values = []
|
234
|
-
data.enum_with_index.inject(0) do |short, ((type, value), i)|
|
235
|
-
n = i % 15
|
236
|
-
last = i+1 == data.size
|
237
|
-
|
238
|
-
if (n == 0 and i != 0) or last
|
239
|
-
if data.size > i+1
|
240
|
-
short |= (1 << 0)
|
241
|
-
elsif last and value
|
242
|
-
values << [type,value]
|
243
|
-
short |= 1<<(15-n)
|
244
|
-
end
|
245
|
-
|
246
|
-
write(:short, short)
|
247
|
-
short = 0
|
248
|
-
end
|
249
|
-
|
250
|
-
if value and !last
|
251
|
-
values << [type,value]
|
252
|
-
short |= 1<<(15-n)
|
253
|
-
end
|
254
|
-
|
255
|
-
short
|
256
|
-
end
|
257
|
-
|
258
|
-
values.each do |type, value|
|
259
|
-
write(type, value) unless type == :bit
|
260
|
-
end
|
261
|
-
else
|
262
|
-
raise Qrack::InvalidTypeError, "Cannot write data of type #{type}"
|
263
|
-
end
|
264
|
-
|
265
|
-
self
|
266
|
-
end
|
267
|
-
|
268
|
-
def extract
|
269
|
-
begin
|
270
|
-
cur_data, cur_pos = @data.clone, @pos
|
271
|
-
yield self
|
272
|
-
rescue Qrack::BufferOverflowError
|
273
|
-
@data, @pos = cur_data, cur_pos
|
274
|
-
nil
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
def _read(size, pack = nil)
|
279
|
-
if @data.is_a?(Qrack::Client)
|
280
|
-
raw = @data.read(size)
|
281
|
-
return raw if raw.nil? or pack.nil?
|
282
|
-
return raw.unpack(pack).first
|
283
|
-
end
|
284
|
-
|
285
|
-
if @pos + size > length
|
286
|
-
raise Qrack::BufferOverflowError
|
287
|
-
else
|
288
|
-
data = @data[@pos,size]
|
289
|
-
@data[@pos,size] = ''
|
290
|
-
if pack
|
291
|
-
data = data.unpack(pack)
|
292
|
-
data = data.pop if data.size == 1
|
293
|
-
end
|
294
|
-
data
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
def _write data, pack = nil
|
299
|
-
data = [*data].pack(pack) if pack
|
300
|
-
@data[@pos,0] = data
|
301
|
-
@pos += data.bytesize
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
|
5
|
-
#:stopdoc:
|
6
|
-
# this file was autogenerated on 2011-07-21 07:07:06 +0100
|
7
|
-
#
|
8
|
-
# DO NOT EDIT! (edit ext/qparser.rb and config.yml instead, and run 'ruby qparser.rb')
|
9
|
-
|
10
|
-
module Qrack
|
11
|
-
module Transport09
|
12
|
-
class Frame
|
13
|
-
|
14
|
-
FOOTER = 206
|
15
|
-
ID = 0
|
16
|
-
|
17
|
-
@types = {
|
18
|
-
1 => 'Method',
|
19
|
-
2 => 'Header',
|
20
|
-
3 => 'Body',
|
21
|
-
8 => 'Heartbeat',
|
22
|
-
}
|
23
|
-
|
24
|
-
attr_accessor :channel, :payload
|
25
|
-
|
26
|
-
def initialize payload = nil, channel = 0
|
27
|
-
@channel, @payload = channel, payload
|
28
|
-
end
|
29
|
-
|
30
|
-
def id
|
31
|
-
self.class::ID
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_binary
|
35
|
-
buf = Transport09::Buffer.new
|
36
|
-
buf.write :octet, id
|
37
|
-
buf.write :short, channel
|
38
|
-
buf.write :longstr, payload
|
39
|
-
buf.write :octet, FOOTER
|
40
|
-
buf.rewind
|
41
|
-
buf
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_s
|
45
|
-
to_binary.to_s
|
46
|
-
end
|
47
|
-
|
48
|
-
def == frame
|
49
|
-
[ :id, :channel, :payload ].inject(true) do |eql, field|
|
50
|
-
eql and __send__(field) == frame.__send__(field)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.parse buf
|
55
|
-
buf = Transport09::Buffer.new(buf) unless buf.is_a? Transport09::Buffer
|
56
|
-
buf.extract do
|
57
|
-
id, channel, payload, footer = buf.read(:octet, :short, :longstr, :octet)
|
58
|
-
Qrack::Transport09.const_get(@types[id]).new(payload, channel) if footer == FOOTER
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
class Method < Frame
|
65
|
-
|
66
|
-
ID = 1
|
67
|
-
|
68
|
-
def initialize payload = nil, channel = 0
|
69
|
-
super
|
70
|
-
unless @payload.is_a? Protocol09::Class::Method or @payload.nil?
|
71
|
-
@payload = Protocol09.parse(@payload)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class Header < Frame
|
77
|
-
|
78
|
-
ID = 2
|
79
|
-
|
80
|
-
def initialize payload = nil, channel = 0
|
81
|
-
super
|
82
|
-
unless @payload.is_a? Protocol09::Header or @payload.nil?
|
83
|
-
@payload = Protocol09::Header.new(@payload)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
class Body < Frame
|
89
|
-
ID = 3
|
90
|
-
end
|
91
|
-
|
92
|
-
class Heartbeat < Frame
|
93
|
-
ID = 8
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
end
|
data/spec/spec_08/bunny_spec.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# bunny_spec.rb
|
4
|
-
|
5
|
-
# Assumes that target message broker/server has a user called 'guest' with a password 'guest'
|
6
|
-
# and that it is running on 'localhost'.
|
7
|
-
|
8
|
-
# If this is not the case, please change the 'Bunny.new' call below to include
|
9
|
-
# the relevant arguments e.g. @b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
|
10
|
-
|
11
|
-
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. lib bunny]))
|
12
|
-
|
13
|
-
describe Bunny do
|
14
|
-
|
15
|
-
before(:each) do
|
16
|
-
@b = Bunny.new
|
17
|
-
@b.start
|
18
|
-
end
|
19
|
-
|
20
|
-
after(:each) do
|
21
|
-
begin
|
22
|
-
@b.stop
|
23
|
-
rescue Exception
|
24
|
-
ensure
|
25
|
-
@b = nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should connect to an AMQP server" do
|
30
|
-
@b.status.should == :connected
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should be able to create and open a new channel" do
|
34
|
-
c = @b.create_channel
|
35
|
-
c.number.should == 2
|
36
|
-
c.should be_an_instance_of(Bunny::Channel)
|
37
|
-
@b.channels.size.should == 3
|
38
|
-
c.open.should == :open_ok
|
39
|
-
@b.channel.number.should == 2
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should be able to switch between channels" do
|
43
|
-
@b.channel.number.should == 1
|
44
|
-
@b.switch_channel(0)
|
45
|
-
@b.channel.number.should == 0
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should raise an error if trying to switch to a non-existent channel" do
|
49
|
-
lambda { @b.switch_channel(5)}.should raise_error(RuntimeError)
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should be able to create an exchange" do
|
53
|
-
exch = @b.exchange('test_exchange')
|
54
|
-
exch.should be_an_instance_of(Bunny::Exchange)
|
55
|
-
exch.name.should == 'test_exchange'
|
56
|
-
@b.exchanges.has_key?('test_exchange').should be(true)
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should be able to create a queue" do
|
60
|
-
q = @b.queue('test1')
|
61
|
-
q.should be_an_instance_of(Bunny::Queue)
|
62
|
-
q.name.should == 'test1'
|
63
|
-
@b.queues.has_key?('test1').should be(true)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should be able to set QoS" do
|
67
|
-
@b.qos.should == :qos_ok
|
68
|
-
end
|
69
|
-
|
70
|
-
it "should be able to set QoS (with global:true)" do
|
71
|
-
@b.qos(:global => true).should == :qos_ok
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|