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.
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