bunny 0.6.3.rc2 → 0.7

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