bunny 0.6.3.rc2 → 0.7
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 +8 -0
- data/.rspec +3 -0
- data/.travis.yml +15 -0
- data/.yardopts +9 -0
- data/CHANGELOG +3 -0
- data/Gemfile +39 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +5 -4
- data/README.textile +54 -0
- data/Rakefile +15 -13
- data/bunny.gemspec +42 -61
- data/examples/simple_08.rb +4 -2
- data/examples/simple_09.rb +4 -2
- data/examples/simple_ack_08.rb +3 -1
- data/examples/simple_ack_09.rb +3 -1
- data/examples/simple_consumer_08.rb +4 -2
- data/examples/simple_consumer_09.rb +4 -2
- data/examples/simple_fanout_08.rb +3 -1
- data/examples/simple_fanout_09.rb +3 -1
- data/examples/simple_headers_08.rb +5 -3
- data/examples/simple_headers_09.rb +5 -3
- data/examples/simple_publisher_08.rb +3 -1
- data/examples/simple_publisher_09.rb +3 -1
- data/examples/simple_topic_08.rb +5 -3
- data/examples/simple_topic_09.rb +5 -3
- data/ext/amqp-0.8.json +616 -0
- data/ext/amqp-0.9.1.json +388 -0
- data/ext/config.yml +4 -0
- data/ext/qparser.rb +463 -0
- data/lib/bunny.rb +88 -66
- data/lib/bunny/channel08.rb +38 -38
- data/lib/bunny/channel09.rb +37 -37
- data/lib/bunny/client08.rb +184 -206
- data/lib/bunny/client09.rb +277 -363
- data/lib/bunny/consumer.rb +35 -0
- data/lib/bunny/exchange08.rb +37 -41
- data/lib/bunny/exchange09.rb +106 -124
- data/lib/bunny/queue08.rb +216 -202
- data/lib/bunny/queue09.rb +256 -326
- data/lib/bunny/subscription08.rb +30 -29
- data/lib/bunny/subscription09.rb +84 -83
- data/lib/bunny/version.rb +5 -0
- data/lib/qrack/amq-client-url.rb +165 -0
- data/lib/qrack/channel.rb +19 -17
- data/lib/qrack/client.rb +152 -151
- data/lib/qrack/errors.rb +5 -0
- data/lib/qrack/protocol/protocol08.rb +132 -130
- data/lib/qrack/protocol/protocol09.rb +133 -131
- data/lib/qrack/protocol/spec08.rb +2 -0
- data/lib/qrack/protocol/spec09.rb +2 -0
- data/lib/qrack/qrack08.rb +7 -10
- data/lib/qrack/qrack09.rb +7 -10
- data/lib/qrack/queue.rb +27 -40
- data/lib/qrack/subscription.rb +102 -101
- data/lib/qrack/transport/buffer08.rb +266 -264
- data/lib/qrack/transport/buffer09.rb +268 -264
- data/lib/qrack/transport/frame08.rb +13 -11
- data/lib/qrack/transport/frame09.rb +9 -7
- data/spec/spec_08/bunny_spec.rb +48 -45
- data/spec/spec_08/connection_spec.rb +10 -7
- data/spec/spec_08/exchange_spec.rb +145 -143
- data/spec/spec_08/queue_spec.rb +161 -161
- data/spec/spec_09/bunny_spec.rb +46 -44
- data/spec/spec_09/connection_spec.rb +15 -8
- data/spec/spec_09/exchange_spec.rb +147 -145
- data/spec/spec_09/queue_spec.rb +182 -184
- metadata +60 -41
- data/README.rdoc +0 -66
@@ -1,133 +1,135 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Qrack
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
4
|
+
module Protocol09
|
5
|
+
#:stopdoc:
|
6
|
+
class Class::Method
|
7
|
+
def initialize *args
|
8
|
+
opts = args.pop if args.last.is_a? Hash
|
9
|
+
opts ||= {}
|
10
|
+
|
11
|
+
if args.size == 1 and args.first.is_a? Transport09::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 = Transport09::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
|
+
Transport09::Method.new(self, channel)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Header
|
66
|
+
def initialize *args
|
67
|
+
opts = args.pop if args.last.is_a? Hash
|
68
|
+
opts ||= {}
|
69
|
+
|
70
|
+
first = args.shift
|
71
|
+
|
72
|
+
if first.is_a? ::Class and first.ancestors.include? Protocol09::Class
|
73
|
+
@klass = first
|
74
|
+
@size = args.shift || 0
|
75
|
+
@weight = args.shift || 0
|
76
|
+
@properties = opts
|
77
|
+
|
78
|
+
elsif first.is_a? Transport09::Buffer or first.is_a? String
|
79
|
+
buf = first
|
80
|
+
buf = Transport09::Buffer.new(buf) unless buf.is_a? Transport09::Buffer
|
81
|
+
|
82
|
+
@klass = Protocol09.classes[buf.read(:short)]
|
83
|
+
@weight = buf.read(:short)
|
84
|
+
@size = buf.read(:longlong)
|
85
|
+
|
86
|
+
props = buf.read(:properties, *klass.properties.map{|type,_| type })
|
87
|
+
@properties = Hash[*klass.properties.map{|_,name| name }.zip(props).reject{|k,v| v.nil? }.flatten]
|
88
|
+
|
89
|
+
else
|
90
|
+
raise ArgumentError, 'Invalid argument'
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
attr_accessor :klass, :size, :weight, :properties
|
95
|
+
|
96
|
+
def to_binary
|
97
|
+
buf = Transport09::Buffer.new
|
98
|
+
buf.write :short, klass.id
|
99
|
+
buf.write :short, weight # XXX rabbitmq only supports weight == 0
|
100
|
+
buf.write :longlong, size
|
101
|
+
buf.write :properties, (klass.properties.map do |type, name|
|
102
|
+
[ type, properties[name] || properties[name.to_s] ]
|
103
|
+
end)
|
104
|
+
buf.rewind
|
105
|
+
buf
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_s
|
109
|
+
to_binary.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_frame channel = 0
|
113
|
+
Transport09::Header.new(self, channel)
|
114
|
+
end
|
115
|
+
|
116
|
+
def == header
|
117
|
+
[ :klass, :size, :weight, :properties ].inject(true) do |eql, field|
|
118
|
+
eql and __send__(field) == header.__send__(field)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def method_missing meth, *args, &blk
|
123
|
+
@properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] :
|
124
|
+
super
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.parse buf
|
129
|
+
buf = Transport09::Buffer.new(buf) unless buf.is_a? Transport09::Buffer
|
130
|
+
class_id, method_id = buf.read(:short, :short)
|
131
|
+
classes[class_id].methods[method_id].new(buf)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
133
135
|
end
|
data/lib/qrack/qrack08.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
$: << File.expand_path(File.dirname(__FILE__))
|
2
4
|
|
3
5
|
require 'protocol/spec08'
|
@@ -9,15 +11,10 @@ require 'transport/frame08'
|
|
9
11
|
require 'qrack/client'
|
10
12
|
require 'qrack/channel'
|
11
13
|
require 'qrack/queue'
|
12
|
-
require '
|
14
|
+
require 'bunny/consumer'
|
15
|
+
require 'qrack/errors'
|
13
16
|
|
14
17
|
module Qrack
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# Errors
|
20
|
-
class BufferOverflowError < StandardError; end
|
21
|
-
class InvalidTypeError < StandardError; end
|
22
|
-
|
23
|
-
end
|
18
|
+
include Protocol
|
19
|
+
include Transport
|
20
|
+
end
|
data/lib/qrack/qrack09.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
$: << File.expand_path(File.dirname(__FILE__))
|
2
4
|
|
3
5
|
require 'protocol/spec09'
|
@@ -9,15 +11,10 @@ require 'transport/frame09'
|
|
9
11
|
require 'qrack/client'
|
10
12
|
require 'qrack/channel'
|
11
13
|
require 'qrack/queue'
|
12
|
-
require '
|
14
|
+
require 'bunny/consumer'
|
15
|
+
require 'qrack/errors'
|
13
16
|
|
14
17
|
module Qrack
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# Errors
|
20
|
-
class BufferOverflowError < StandardError; end
|
21
|
-
class InvalidTypeError < StandardError; end
|
22
|
-
|
23
|
-
end
|
18
|
+
include Protocol09
|
19
|
+
include Transport09
|
20
|
+
end
|
data/lib/qrack/queue.rb
CHANGED
@@ -1,53 +1,40 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Queue ancestor class
|
4
|
-
class Queue
|
5
|
-
|
6
|
-
attr_reader :name, :client
|
7
|
-
attr_accessor :delivery_tag, :subscription
|
8
|
-
|
9
|
-
=begin rdoc
|
10
|
-
|
11
|
-
=== DESCRIPTION:
|
12
|
-
|
13
|
-
Returns consumer count from Queue#status.
|
1
|
+
# encoding: utf-8
|
14
2
|
|
15
|
-
|
16
|
-
|
17
|
-
def consumer_count
|
18
|
-
s = status
|
19
|
-
s[:consumer_count]
|
20
|
-
end
|
21
|
-
|
22
|
-
=begin rdoc
|
3
|
+
module Qrack
|
23
4
|
|
24
|
-
|
5
|
+
# Queue ancestor class
|
6
|
+
class Queue
|
25
7
|
|
26
|
-
|
8
|
+
# @return [AMQ::Client::Consumer] Default consumer (registered with {Queue#subscribe}).
|
9
|
+
attr_accessor :default_consumer
|
27
10
|
|
28
|
-
|
11
|
+
attr_reader :name, :client
|
29
12
|
|
30
|
-
|
31
|
-
s = status
|
32
|
-
s[:message_count]
|
33
|
-
end
|
13
|
+
attr_accessor :delivery_tag
|
34
14
|
|
35
|
-
=begin rdoc
|
36
15
|
|
37
|
-
|
16
|
+
# Returns consumer count from {Queue#status}.
|
17
|
+
def consumer_count
|
18
|
+
s = status
|
19
|
+
s[:consumer_count]
|
20
|
+
end
|
38
21
|
|
39
|
-
|
22
|
+
# Returns message count from {Queue#status}.
|
23
|
+
def message_count
|
24
|
+
s = status
|
25
|
+
s[:message_count]
|
26
|
+
end
|
40
27
|
|
41
|
-
|
28
|
+
# Publishes a message to the queue via the default nameless '' direct exchange.
|
42
29
|
|
43
|
-
nil
|
30
|
+
# @return [NilClass] nil
|
31
|
+
# @deprecated
|
32
|
+
# @note This method will be removed before 0.8 release.
|
33
|
+
def publish(data, opts = {})
|
34
|
+
Bunny.deprecation_warning("Qrack::Queue#publish", "0.8")
|
35
|
+
exchange.publish(data, opts)
|
36
|
+
end
|
44
37
|
|
45
|
-
|
38
|
+
end
|
46
39
|
|
47
|
-
def publish(data, opts = {})
|
48
|
-
exchange.publish(data, opts)
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
40
|
end
|
data/lib/qrack/subscription.rb
CHANGED
@@ -1,102 +1,103 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#################################################
|
4
|
+
# WARNING: THIS CLASS IS DEPRECATED, DO NOT #
|
5
|
+
# USE IT DIRECTLY! USE BUNNY::CONSUMER INSTEAD! #
|
6
|
+
#################################################
|
7
|
+
|
1
8
|
module Qrack
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
9
|
+
# Subscription ancestor class
|
10
|
+
# @deprecated
|
11
|
+
class Subscription
|
12
|
+
|
13
|
+
attr_accessor :consumer_tag, :delivery_tag, :message_max, :timeout, :ack, :exclusive
|
14
|
+
attr_reader :client, :queue, :message_count
|
15
|
+
|
16
|
+
def initialize(client, queue, opts = {})
|
17
|
+
@client = client
|
18
|
+
@queue = queue
|
19
|
+
|
20
|
+
# Get timeout value
|
21
|
+
@timeout = opts[:timeout] || nil
|
22
|
+
|
23
|
+
# Get maximum amount of messages to process
|
24
|
+
@message_max = opts[:message_max] || nil
|
25
|
+
|
26
|
+
# If a consumer tag is not passed in the server will generate one
|
27
|
+
@consumer_tag = opts[:consumer_tag] || nil
|
28
|
+
|
29
|
+
# Ignore the :nowait option if passed, otherwise program will hang waiting for a
|
30
|
+
# response from the server causing an error.
|
31
|
+
opts.delete(:nowait)
|
32
|
+
|
33
|
+
# Do we want to have to provide an acknowledgement?
|
34
|
+
@ack = opts[:ack] || nil
|
35
|
+
|
36
|
+
# Does this consumer want exclusive use of the queue?
|
37
|
+
@exclusive = opts[:exclusive] || false
|
38
|
+
|
39
|
+
# Initialize message counter
|
40
|
+
@message_count = 0
|
41
|
+
|
42
|
+
# Store options
|
43
|
+
@opts = opts
|
44
|
+
end
|
45
|
+
|
46
|
+
def start(&blk)
|
47
|
+
# Do not process any messages if zero message_max
|
48
|
+
if message_max == 0
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
# Notify server about new consumer
|
53
|
+
setup_consumer
|
54
|
+
|
55
|
+
# Start subscription loop
|
56
|
+
loop do
|
57
|
+
|
58
|
+
begin
|
59
|
+
method = client.next_method(:timeout => timeout)
|
60
|
+
rescue Qrack::ClientTimeout
|
61
|
+
queue.unsubscribe
|
62
|
+
break
|
63
|
+
end
|
64
|
+
|
65
|
+
# Increment message counter
|
66
|
+
@message_count += 1
|
67
|
+
|
68
|
+
# get delivery tag to use for acknowledge
|
69
|
+
queue.delivery_tag = method.delivery_tag if @ack
|
70
|
+
|
71
|
+
header = client.next_payload
|
72
|
+
|
73
|
+
# If maximum frame size is smaller than message payload body then message
|
74
|
+
# will have a message header and several message bodies
|
75
|
+
msg = ''
|
76
|
+
while msg.length < header.size
|
77
|
+
msg << client.next_payload
|
78
|
+
end
|
79
|
+
|
80
|
+
# If block present, pass the message info to the block for processing
|
81
|
+
blk.call({:header => header, :payload => msg, :delivery_details => method.arguments}) if !blk.nil?
|
82
|
+
|
83
|
+
# Exit loop if message_max condition met
|
84
|
+
if (!message_max.nil? and message_count == message_max)
|
85
|
+
# Stop consuming messages
|
86
|
+
queue.unsubscribe()
|
87
|
+
# Acknowledge receipt of the final message
|
88
|
+
queue.ack() if @ack
|
89
|
+
# Quit the loop
|
90
|
+
break
|
91
|
+
end
|
92
|
+
|
93
|
+
# Have to do the ack here because the ack triggers the release of messages from the server
|
94
|
+
# if you are using Client#qos prefetch and you will get extra messages sent through before
|
95
|
+
# the unsubscribe takes effect to stop messages being sent to this consumer unless the ack is
|
96
|
+
# deferred.
|
97
|
+
queue.ack() if @ack
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|