bunny 0.2.0 → 0.3.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Duncan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,49 @@
1
+ = Bunny: A synchronous Ruby AMQP client
2
+
3
+ *GitHub* *repo*: http://github.com/celldee/bunny
4
+
5
+ === DESCRIPTION:
6
+
7
+ Bunny is an AMQP[http://www.amqp.org] (Advanced Message Queuing Protocol) client, written in Ruby, that is intended to allow you to interact with AMQP-compliant message brokers/servers such as RabbitMQ[http://www.rabbitmq.com] in a synchronous fashion.
8
+
9
+ It is based on a great deal of useful code from amqp[http://github.com/tmm1/amqp] by Aman Gupta and Carrot[http://github.com/famoseagle/carrot] by Amos Elliston.
10
+
11
+ You can use Bunny to -
12
+
13
+ * Create and delete exchanges
14
+ * Create and delete queues
15
+ * Publish and consume messages
16
+
17
+ Bunny is known to work with RabbitMQ version 1.5.4 and version 0-8 of the AMQP specification.
18
+
19
+ === INSTALL:
20
+
21
+ *Rubyforge*: <tt>gem install bunny</tt>
22
+
23
+ *GitHub*: <tt>gem install celldee-bunny</tt>
24
+
25
+ === QUICK START:
26
+
27
+ require 'bunny'
28
+
29
+ b = Bunny::Client.new(:logging => true)
30
+
31
+ # start a communication session with the amqp server
32
+ b.start
33
+
34
+ # declare a queue
35
+ q = b.queue('test1')
36
+
37
+ # publish a message to the queue
38
+ q.publish('Hello everybody!')
39
+
40
+ # get message from the queue
41
+ msg = q.pop
42
+
43
+ puts 'This is the message: ' + msg + "\n\n"
44
+
45
+ # close the connection
46
+ b.stop
47
+
48
+ === OTHER:
49
+ Please see the _examples_ directory for additional usage information.
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  task :codegen do
2
- sh 'ruby protocol/codegen.rb > lib/amqp/spec.rb'
3
- sh 'ruby lib/amqp/spec.rb'
2
+ sh 'ruby ext/codegen.rb > lib/bunny/protocol/spec.rb'
3
+ sh 'ruby lib/bunny/protocol/spec.rb'
4
4
  end
5
5
 
6
6
  task :spec do
@@ -8,5 +8,4 @@ task :spec do
8
8
  Spec::Rake::SpecTask.new do |t|
9
9
  t.spec_opts = ['--color']
10
10
  end
11
- end
12
-
11
+ end
@@ -0,0 +1,37 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{bunny}
3
+ s.version = "0.3.0"
4
+ s.authors = ["Chris Duncan"]
5
+ s.date = %q{2009-05-10}
6
+ s.description = %q{Another synchronous Ruby AMQP client}
7
+ s.email = %q{celldee@gmail.com}
8
+ s.rubyforge_project = %q{bunny-amqp}
9
+ s.has_rdoc = true
10
+ s.extra_rdoc_files = [ "README" ]
11
+ s.rdoc_options = [ "--main", "README" ]
12
+ s.homepage = %q{http://github.com/celldee/bunny}
13
+ s.summary = %q{A synchronous Ruby AMQP client that enables interaction with AMQP-compliant brokers/servers.}
14
+ s.files = ["LICENSE",
15
+ "README",
16
+ "Rakefile",
17
+ "bunny.gemspec",
18
+ "examples/simple.rb",
19
+ "examples/simple_ack.rb",
20
+ "examples/simple_consumer.rb",
21
+ "examples/simple_fanout.rb",
22
+ "examples/simple_publisher.rb",
23
+ "examples/simple_topic.rb",
24
+ "ext/amqp-0.8.json",
25
+ "ext/codegen.rb",
26
+ "lib/bunny.rb",
27
+ "lib/bunny/client.rb",
28
+ "lib/bunny/exchange.rb",
29
+ "lib/bunny/protocol/protocol.rb",
30
+ "lib/bunny/protocol/spec.rb",
31
+ "lib/bunny/queue.rb",
32
+ "lib/bunny/transport/buffer.rb",
33
+ "lib/bunny/transport/frame.rb",
34
+ "spec/bunny_spec.rb",
35
+ "spec/exchange_spec.rb",
36
+ "spec/queue_spec.rb"]
37
+ end
@@ -10,7 +10,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
10
10
 
11
11
  require 'bunny'
12
12
 
13
- b = Bunny.new(:logging => true)
13
+ b = Bunny::Client.new(:logging => true)
14
14
 
15
15
  # start a communication session with the amqp server
16
16
  b.start
@@ -10,7 +10,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
10
10
 
11
11
  require 'bunny'
12
12
 
13
- b = Bunny.new(:logging => true)
13
+ b = Bunny::Client.new(:logging => true)
14
14
 
15
15
  # start a communication session with the amqp server
16
16
  b.start
@@ -27,7 +27,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
27
27
 
28
28
  require 'bunny'
29
29
 
30
- b = Bunny.new(:logging => true)
30
+ b = Bunny::Client.new(:logging => true)
31
31
 
32
32
  # start a communication session with the amqp server
33
33
  b.start
@@ -10,7 +10,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
10
10
 
11
11
  require 'bunny'
12
12
 
13
- b = Bunny.new(:logging => true)
13
+ b = Bunny::Client.new(:logging => true)
14
14
 
15
15
  # start a communication session with the amqp server
16
16
  b.start
@@ -12,7 +12,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
12
12
 
13
13
  require 'bunny'
14
14
 
15
- b = Bunny.new(:logging => true)
15
+ b = Bunny::Client.new(:logging => true)
16
16
 
17
17
  # start a communication session with the amqp server
18
18
  b.start
@@ -10,7 +10,7 @@ $:.unshift File.dirname(__FILE__) + '/../lib'
10
10
 
11
11
  require 'bunny'
12
12
 
13
- b = Bunny.new
13
+ b = Bunny::Client.new
14
14
 
15
15
  # start a communication session with the amqp server
16
16
  b.start
@@ -50,9 +50,9 @@ msg = rugby.pop
50
50
  puts 'This is a message from the rugby q: ' + msg + "\n\n"
51
51
 
52
52
  # allsport queue got all of the messages
53
- until msg == 'QUEUE EMPTY' do
53
+ until msg == :queue_empty do
54
54
  msg = allsport.pop
55
- puts 'This is a message from the allsport q: ' + msg + "\n\n" unless msg == 'QUEUE EMPTY'
55
+ puts 'This is a message from the allsport q: ' + msg + "\n\n" unless msg == :queue_empty
56
56
  end
57
57
 
58
58
  # close the client connection
File without changes
@@ -0,0 +1,177 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+
4
+ name = 'amqp-0.8.json'
5
+ path = File.dirname(__FILE__)+'/'+name
6
+ s = JSON.parse(File.read(path))
7
+
8
+ # require 'pp'
9
+ # pp(s)
10
+ # exit
11
+
12
+ require 'erb'
13
+
14
+ puts ERB.new(%q[
15
+ #:stopdoc:
16
+ # this file was autogenerated on <%= Time.now.to_s %>
17
+ # using <%= name.ljust(16) %> (mtime: <%= File.mtime(path) %>)
18
+ #
19
+ # DO NOT EDIT! (edit ext/codegen.rb instead, and run `rake codegen`)
20
+
21
+ module Bunny
22
+ module Transport
23
+ class Frame
24
+ def self.types
25
+ @types ||= {}
26
+ end
27
+
28
+ def self.Frame id
29
+ (@_base_frames ||= {})[id] ||= Class.new(Frame) do
30
+ class_eval %[
31
+ def self.inherited klass
32
+ klass.const_set(:ID, #{id})
33
+ Frame.types[#{id}] = klass
34
+ end
35
+ ]
36
+ end
37
+ end
38
+
39
+ <%- s['constants'].select{|c| (1..8).include? c['value'] }.each do |c| -%>
40
+ class <%= c['name'].gsub(/^FRAME-/,'').split('-').map{|w| w.downcase.capitalize}.join.ljust(9) -%> < Frame( <%= c['value'] -%> ); end
41
+ <%- end -%>
42
+
43
+ FOOTER = <%= frame_end = s['constants'].find{|c| c['name'] == 'FRAME-END' }['value'] %>
44
+ end
45
+ end
46
+ end
47
+
48
+ module Bunny
49
+ module Protocol
50
+ HEADER = <%= s['name'].dump %>.freeze
51
+ VERSION_MAJOR = <%= s['major-version'] %>
52
+ VERSION_MINOR = <%= s['minor-version'] %>
53
+ PORT = <%= s['port'] %>
54
+
55
+ RESPONSES = {
56
+ <%- s['constants'].select{|c| c['value'] != frame_end and (200..500).include? c['value'] }.each do |c| -%>
57
+ <%= c['value'] %> => :<%= c['name'].tr('-', '_').gsub(/^FRAME_/,'').upcase -%>,
58
+ <%- end -%>
59
+ }
60
+
61
+ FIELDS = [
62
+ <%- s['domains'].select{|d| d.first == d.last }.each do |d| -%>
63
+ :<%= d.first -%>,
64
+ <%- end -%>
65
+ ]
66
+
67
+ class Class
68
+ class << self
69
+ FIELDS.each do |f|
70
+ class_eval %[
71
+ def #{f} name
72
+ properties << [ :#{f}, name ] unless properties.include?([:#{f}, name])
73
+ attr_accessor name
74
+ end
75
+ ]
76
+ end
77
+
78
+ def properties() @properties ||= [] end
79
+
80
+ def id() self::ID end
81
+ def name() self::NAME end
82
+ end
83
+
84
+ class Method
85
+ class << self
86
+ FIELDS.each do |f|
87
+ class_eval %[
88
+ def #{f} name
89
+ arguments << [ :#{f}, name ] unless arguments.include?([:#{f}, name])
90
+ attr_accessor name
91
+ end
92
+ ]
93
+ end
94
+
95
+ def arguments() @arguments ||= [] end
96
+
97
+ def parent() Protocol.const_get(self.to_s[/Protocol::(.+?)::/,1]) end
98
+ def id() self::ID end
99
+ def name() self::NAME end
100
+ end
101
+
102
+ def == b
103
+ self.class.arguments.inject(true) do |eql, (type, name)|
104
+ eql and __send__("#{name}") == b.__send__("#{name}")
105
+ end
106
+ end
107
+ end
108
+
109
+ def self.methods() @methods ||= {} end
110
+
111
+ def self.Method(id, name)
112
+ @_base_methods ||= {}
113
+ @_base_methods[id] ||= ::Class.new(Method) do
114
+ class_eval %[
115
+ def self.inherited klass
116
+ klass.const_set(:ID, #{id})
117
+ klass.const_set(:NAME, :#{name.to_s})
118
+ klass.parent.methods[#{id}] = klass
119
+ klass.parent.methods[klass::NAME] = klass
120
+ end
121
+ ]
122
+ end
123
+ end
124
+ end
125
+
126
+ def self.classes() @classes ||= {} end
127
+
128
+ def self.Class(id, name)
129
+ @_base_classes ||= {}
130
+ @_base_classes[id] ||= ::Class.new(Class) do
131
+ class_eval %[
132
+ def self.inherited klass
133
+ klass.const_set(:ID, #{id})
134
+ klass.const_set(:NAME, :#{name.to_s})
135
+ Protocol.classes[#{id}] = klass
136
+ Protocol.classes[klass::NAME] = klass
137
+ end
138
+ ]
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ module Bunny
145
+ module Protocol
146
+ <%- s['classes'].each do |c| -%>
147
+ class <%= c['name'].capitalize.ljust(12) %> < Class( <%= c['id'].to_s.rjust(3) %>, :<%= c['name'].ljust(12) %> ); end
148
+ <%- end -%>
149
+
150
+ <%- s['classes'].each do |c| -%>
151
+ class <%= c['name'].capitalize %>
152
+ <%- c['properties'].each do |p| -%>
153
+ <%= p['type'].ljust(10) %> :<%= p['name'].tr('-','_') %>
154
+ <%- end if c['properties'] -%>
155
+
156
+ <%- c['methods'].each do |m| -%>
157
+ class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"}.ljust(12) %> < Method( <%= m['id'].to_s.rjust(3) %>, :<%= m['name'].tr('- ','_').ljust(14) %> ); end
158
+ <%- end -%>
159
+
160
+ <%- c['methods'].each do |m| -%>
161
+ class <%= m['name'].capitalize.gsub(/-(.)/){ "#{$1.upcase}"} %>
162
+ <%- m['arguments'].each do |a| -%>
163
+ <%- if a['domain'] -%>
164
+ <%= s['domains'].find{|k,v| k == a['domain']}.last.ljust(10) %> :<%= a['name'].tr('- ','_') %>
165
+ <%- else -%>
166
+ <%= a['type'].ljust(10) %> :<%= a['name'].tr('- ','_') %>
167
+ <%- end -%>
168
+ <%- end if m['arguments'] -%>
169
+ end
170
+
171
+ <%- end -%>
172
+ end
173
+
174
+ <%- end -%>
175
+ end
176
+ end
177
+ ].gsub!(/^ /,''), nil, '>-%').result(binding)
@@ -5,76 +5,34 @@ $:.unshift File.expand_path(File.dirname(__FILE__))
5
5
  require file
6
6
  end
7
7
 
8
- # AMQP protocol and transport
9
- %w[spec protocol buffer frame].each do |file|
10
- require 'engineroom/' + file
11
- end
8
+ require 'bunny/client'
9
+ require 'bunny/exchange'
10
+ require 'bunny/queue'
12
11
 
13
- # Bunny API
14
- %w[client exchange header queue].each do |file|
15
- require 'bunny/' + file
16
- end
12
+ require 'bunny/protocol/spec'
13
+ require 'bunny/protocol/protocol'
17
14
 
18
- # Error and return message definitions
19
- require 'api_messages'
15
+ require 'bunny/transport/buffer'
16
+ require 'bunny/transport/frame'
20
17
 
21
- class Bunny
18
+ module Bunny
19
+
22
20
  include Protocol
23
21
  include Transport
24
- include API
25
22
 
26
- attr_reader :client
27
-
28
- def initialize(opts = {})
29
- @client = API::Client.new(opts)
30
- end
31
-
32
- def logging=(bool)
33
- client.logging = bool
34
- end
23
+ class ProtocolError < StandardError; end
24
+ class ServerDownError < StandardError; end
25
+ class BufferOverflowError < StandardError; end
26
+ class InvalidTypeError < StandardError; end
27
+ class ConnectionError < StandardError; end
28
+ class MessageError < StandardError; end
35
29
 
36
- def logging
37
- client.logging
38
- end
39
-
40
- def start
41
- client.start_session
42
- end
43
-
44
- def status
45
- client.status
46
- end
30
+ VERSION = '0.3.0'
47
31
 
48
- def exchange(name, opts = {})
49
- client.exchanges[name] ||= API::Exchange.new(client, name, opts)
50
- end
51
-
52
- def queue(name, opts = {})
53
- client.queues[name] ||= API::Queue.new(client, name, opts)
54
- end
55
-
56
- def stop
57
- client.close
58
- end
59
-
60
- def queues
61
- client.queues ||= {}
62
- end
32
+ # Returns the Bunny version number
63
33
 
64
- def exchanges
65
- client.exchanges ||= {}
66
- end
67
-
68
- def host
69
- client.host
70
- end
71
-
72
- def vhost
73
- client.vhost
74
- end
75
-
76
- def port
77
- client.port
34
+ def self.version
35
+ VERSION
78
36
  end
79
-
37
+
80
38
  end