amqp 0.7.0.pre → 0.7.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.
Files changed (71) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +2 -0
  3. data/CHANGELOG +8 -2
  4. data/CONTRIBUTORS +22 -0
  5. data/Gemfile +3 -3
  6. data/README.md +20 -11
  7. data/Rakefile +30 -6
  8. data/amqp.gemspec +1 -1
  9. data/bin/cleanify.rb +50 -0
  10. data/examples/amqp/simple.rb +6 -4
  11. data/examples/mq/ack.rb +8 -6
  12. data/examples/mq/automatic_binding_for_default_direct_exchange.rb +65 -0
  13. data/examples/mq/callbacks.rb +9 -1
  14. data/examples/mq/clock.rb +17 -17
  15. data/examples/mq/hashtable.rb +19 -10
  16. data/examples/mq/internal.rb +13 -11
  17. data/examples/mq/logger.rb +38 -36
  18. data/examples/mq/multiclock.rb +16 -7
  19. data/examples/mq/pingpong.rb +16 -7
  20. data/examples/mq/pop.rb +8 -6
  21. data/examples/mq/primes-simple.rb +2 -0
  22. data/examples/mq/primes.rb +7 -5
  23. data/examples/mq/stocks.rb +14 -5
  24. data/lib/amqp.rb +12 -8
  25. data/lib/amqp/buffer.rb +35 -158
  26. data/lib/amqp/client.rb +34 -22
  27. data/lib/amqp/frame.rb +8 -64
  28. data/lib/amqp/protocol.rb +21 -70
  29. data/lib/amqp/server.rb +11 -9
  30. data/lib/amqp/spec.rb +8 -6
  31. data/lib/amqp/version.rb +2 -0
  32. data/lib/ext/blankslate.rb +3 -1
  33. data/lib/ext/em.rb +2 -0
  34. data/lib/ext/emfork.rb +13 -11
  35. data/lib/mq.rb +253 -156
  36. data/lib/mq/collection.rb +6 -88
  37. data/lib/mq/exchange.rb +70 -13
  38. data/lib/mq/header.rb +12 -6
  39. data/lib/mq/logger.rb +9 -7
  40. data/lib/mq/queue.rb +42 -30
  41. data/lib/mq/rpc.rb +6 -4
  42. data/protocol/codegen.rb +20 -18
  43. data/research/api.rb +10 -46
  44. data/research/primes-forked.rb +9 -7
  45. data/research/primes-processes.rb +74 -72
  46. data/research/primes-threaded.rb +9 -7
  47. data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +61 -0
  48. data/spec/mq_helper.rb +70 -0
  49. data/spec/spec_helper.rb +84 -29
  50. data/spec/unit/amqp/buffer_spec.rb +178 -0
  51. data/spec/unit/amqp/client_spec.rb +472 -0
  52. data/spec/unit/amqp/frame_spec.rb +60 -0
  53. data/spec/unit/amqp/misc_spec.rb +123 -0
  54. data/spec/unit/amqp/protocol_spec.rb +53 -0
  55. data/spec/unit/mq/channel_close_spec.rb +15 -0
  56. data/spec/unit/mq/collection_spec.rb +129 -0
  57. data/spec/unit/mq/exchange_declaration_spec.rb +524 -0
  58. data/spec/unit/mq/misc_spec.rb +228 -0
  59. data/spec/unit/mq/mq_basic_spec.rb +39 -0
  60. data/spec/unit/mq/queue_declaration_spec.rb +97 -0
  61. data/spec/unit/mq/queue_spec.rb +71 -0
  62. metadata +33 -21
  63. data/Gemfile.lock +0 -16
  64. data/old/README +0 -30
  65. data/old/Rakefile +0 -12
  66. data/old/amqp-0.8.json +0 -606
  67. data/old/amqp_spec.rb +0 -796
  68. data/old/amqpc.rb +0 -695
  69. data/old/codegen.rb +0 -148
  70. data/spec/channel_close_spec.rb +0 -13
  71. data/spec/sync_async_spec.rb +0 -52
@@ -1,10 +1,12 @@
1
+ # encoding: utf-8
2
+
1
3
  require File.expand_path('../spec', __FILE__)
2
4
  require File.expand_path('../buffer', __FILE__)
3
5
  require File.expand_path('../protocol', __FILE__)
4
6
 
5
7
  module AMQP
6
8
  class Frame #:nodoc: all
7
- def initialize payload = nil, channel = 0
9
+ def initialize(payload = nil, channel = 0)
8
10
  @channel, @payload = channel, payload
9
11
  end
10
12
  attr_accessor :channel, :payload
@@ -12,7 +14,7 @@ module AMQP
12
14
  def id
13
15
  self.class::ID
14
16
  end
15
-
17
+
16
18
  def to_binary
17
19
  buf = Buffer.new
18
20
  buf.write :octet, id
@@ -32,11 +34,11 @@ module AMQP
32
34
  eql and __send__(field) == frame.__send__(field)
33
35
  end
34
36
  end
35
-
37
+
36
38
  class Invalid < StandardError; end
37
-
39
+
38
40
  class Method
39
- def initialize payload = nil, channel = 0
41
+ def initialize(payload = nil, channel = 0)
40
42
  super
41
43
  unless @payload.is_a? Protocol::Class::Method or @payload.nil?
42
44
  @payload = Protocol.parse(@payload)
@@ -45,7 +47,7 @@ module AMQP
45
47
  end
46
48
 
47
49
  class Header
48
- def initialize payload = nil, channel = 0
50
+ def initialize(payload = nil, channel = 0)
49
51
  super
50
52
  unless @payload.is_a? Protocol::Header or @payload.nil?
51
53
  @payload = Protocol::Header.new(@payload)
@@ -64,61 +66,3 @@ module AMQP
64
66
  end
65
67
  end
66
68
  end
67
-
68
- if $0 =~ /bacon/ or $0 == __FILE__
69
- require 'bacon'
70
- include AMQP
71
-
72
- describe Frame do
73
- should 'handle basic frame types' do
74
- Frame::Method.new.id.should == 1
75
- Frame::Header.new.id.should == 2
76
- Frame::Body.new.id.should == 3
77
- end
78
-
79
- should 'convert method frames to binary' do
80
- meth = Protocol::Connection::Secure.new :challenge => 'secret'
81
-
82
- frame = Frame::Method.new(meth)
83
- frame.to_binary.should.be.kind_of? Buffer
84
- frame.to_s.should == [ 1, 0, meth.to_s.length, meth.to_s, 206 ].pack('CnNa*C')
85
- end
86
-
87
- should 'convert binary to method frames' do
88
- orig = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
89
-
90
- copy = Frame.parse(orig.to_binary)
91
- copy.should == orig
92
- end
93
-
94
- should 'ignore partial frames until ready' do
95
- frame = Frame::Method.new Protocol::Connection::Secure.new(:challenge => 'secret')
96
- data = frame.to_s
97
-
98
- buf = Buffer.new
99
- Frame.parse(buf).should == nil
100
-
101
- buf << data[0..5]
102
- Frame.parse(buf).should == nil
103
-
104
- buf << data[6..-1]
105
- Frame.parse(buf).should == frame
106
-
107
- Frame.parse(buf).should == nil
108
- end
109
-
110
- should 'convert header frames to binary' do
111
- head = Protocol::Header.new(Protocol::Basic, :priority => 1)
112
-
113
- frame = Frame::Header.new(head)
114
- frame.to_s.should == [ 2, 0, head.to_s.length, head.to_s, 206 ].pack('CnNa*C')
115
- end
116
-
117
- should 'convert binary to header frame' do
118
- orig = Frame::Header.new Protocol::Header.new(Protocol::Basic, :priority => 1)
119
-
120
- copy = Frame.parse(orig.to_binary)
121
- copy.should == orig
122
- end
123
- end
124
- end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require File.expand_path('../spec', __FILE__)
2
4
  require File.expand_path('../buffer', __FILE__)
3
5
 
@@ -5,12 +7,12 @@ module AMQP
5
7
  module Protocol
6
8
  #:stopdoc:
7
9
  class Class::Method
8
- def initialize *args
10
+ def initialize(*args)
9
11
  opts = args.pop if args.last.is_a? Hash
10
12
  opts ||= {}
11
-
13
+
12
14
  @debug = 1 # XXX hack, p(obj) == '' if no instance vars are set
13
-
15
+
14
16
  if args.size == 1 and args.first.is_a? Buffer
15
17
  buf = args.shift
16
18
  else
@@ -55,19 +57,19 @@ module AMQP
55
57
 
56
58
  buf
57
59
  end
58
-
60
+
59
61
  def to_s
60
62
  to_binary.to_s
61
63
  end
62
-
63
- def to_frame channel = 0
64
+
65
+ def to_frame(channel = 0)
64
66
  Frame::Method.new(self, channel)
65
67
  end
66
68
  end
67
69
 
68
70
  #:startdoc:
69
71
  #
70
- # Contains a properties hash that holds some potentially interesting
72
+ # Contains a properties hash that holds some potentially interesting
71
73
  # information.
72
74
  # * :delivery_mode
73
75
  # 1 equals transient.
@@ -89,12 +91,12 @@ module AMQP
89
91
  # A monotonically increasing integer. This number should not be trusted
90
92
  # as a sequence number. There is no guarantee it won't get reset.
91
93
  class Header
92
- def initialize *args
94
+ def initialize(*args)
93
95
  opts = args.pop if args.last.is_a? Hash
94
96
  opts ||= {}
95
-
97
+
96
98
  first = args.shift
97
-
99
+
98
100
  if first.is_a? ::Class and first.ancestors.include? Protocol::Class
99
101
  @klass = first
100
102
  @size = args.shift || 0
@@ -104,21 +106,21 @@ module AMQP
104
106
  elsif first.is_a? Buffer or first.is_a? String
105
107
  buf = first
106
108
  buf = Buffer.new(buf) unless buf.is_a? Buffer
107
-
109
+
108
110
  @klass = Protocol.classes[buf.read(:short)]
109
111
  @weight = buf.read(:short)
110
112
  @size = buf.read(:longlong)
111
113
 
112
- props = buf.read(:properties, *klass.properties.map{|type,_| type })
113
- @properties = Hash[*klass.properties.map{|_,name| name }.zip(props).reject{|k,v| v.nil? }.flatten]
114
+ props = buf.read(:properties, *klass.properties.map { |type, _| type })
115
+ @properties = Hash[*klass.properties.map { |_, name| name }.zip(props).reject { |k, v| v.nil? }.flatten]
114
116
 
115
117
  else
116
118
  raise ArgumentError, 'Invalid argument'
117
119
  end
118
-
120
+
119
121
  end
120
122
  attr_accessor :klass, :size, :weight, :properties
121
-
123
+
122
124
  def to_binary
123
125
  buf = Buffer.new
124
126
  buf.write :short, klass.id
@@ -130,12 +132,12 @@ module AMQP
130
132
  buf.rewind
131
133
  buf
132
134
  end
133
-
135
+
134
136
  def to_s
135
137
  to_binary.to_s
136
138
  end
137
139
 
138
- def to_frame channel = 0
140
+ def to_frame(channel = 0)
139
141
  Frame::Header.new(self, channel)
140
142
  end
141
143
 
@@ -145,8 +147,8 @@ module AMQP
145
147
  end
146
148
  end
147
149
 
148
- def method_missing meth, *args, &blk
149
- @properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] :
150
+ def method_missing(meth, *args, &blk)
151
+ @properties.has_key?(meth) || @klass.properties.find { |_, name| name == meth } ? @properties[meth] :
150
152
  super
151
153
  end
152
154
  end
@@ -159,54 +161,3 @@ module AMQP
159
161
  #:stopdoc:
160
162
  end
161
163
  end
162
-
163
- if $0 =~ /bacon/ or $0 == __FILE__
164
- require 'bacon'
165
- include AMQP
166
-
167
- describe Protocol do
168
- should 'instantiate methods with arguments' do
169
- meth = Protocol::Connection::StartOk.new nil, 'PLAIN', nil, 'en_US'
170
- meth.locale.should == 'en_US'
171
- end
172
-
173
- should 'instantiate methods with named parameters' do
174
- meth = Protocol::Connection::StartOk.new :locale => 'en_US',
175
- :mechanism => 'PLAIN'
176
- meth.locale.should == 'en_US'
177
- end
178
-
179
- should 'convert methods to binary' do
180
- meth = Protocol::Connection::Secure.new :challenge => 'secret'
181
- meth.to_binary.should.be.kind_of? Buffer
182
-
183
- meth.to_s.should == [ 10, 20, 6, 'secret' ].pack('nnNa*')
184
- end
185
-
186
- should 'convert binary to method' do
187
- orig = Protocol::Connection::Secure.new :challenge => 'secret'
188
- copy = Protocol.parse orig.to_binary
189
- orig.should == copy
190
- end
191
-
192
- should 'convert headers to binary' do
193
- head = Protocol::Header.new Protocol::Basic,
194
- size = 5,
195
- weight = 0,
196
- :content_type => 'text/json',
197
- :delivery_mode => 1,
198
- :priority => 1
199
- head.to_s.should == [ 60, weight, 0, size, 0b1001_1000_0000_0000, 9, 'text/json', 1, 1 ].pack('nnNNnCa*CC')
200
- end
201
-
202
- should 'convert binary to header' do
203
- orig = Protocol::Header.new Protocol::Basic,
204
- size = 5,
205
- weight = 0,
206
- :content_type => 'text/json',
207
- :delivery_mode => 1,
208
- :priority => 1
209
- Protocol::Header.new(orig.to_binary).should == orig
210
- end
211
- end
212
- end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require File.expand_path('../frame', __FILE__)
2
4
 
3
5
  module AMQP
@@ -8,17 +10,17 @@ module AMQP
8
10
  @started = false
9
11
  end
10
12
 
11
- def receive_data data
13
+ def receive_data(data)
12
14
  @buf << data
13
15
 
14
16
  unless @started
15
17
  if @buf.size >= 8
16
- if @buf.slice!(0,8) == "AMQP\001\001\b\000"
18
+ if @buf.slice!(0, 8) == "AMQP\001\001\b\000"
17
19
  send Protocol::Connection::Start.new(
18
20
  8,
19
21
  0,
20
22
  {
21
- :information => 'Licensed under the Ruby license. See http://github.com/tmm1/amqp',
23
+ :information => 'Licensed under the Ruby license. See http://github.com/ruby-amqp/amqp',
22
24
  :copyright => 'Copyright (c) 2008-2009 Aman Gupta',
23
25
  :platform => 'Ruby/EventMachine',
24
26
  :version => '0.6.1',
@@ -42,7 +44,7 @@ module AMQP
42
44
  end
43
45
  end
44
46
 
45
- def process_frame frame
47
+ def process_frame(frame)
46
48
  channel = frame.channel
47
49
 
48
50
  case method = frame.payload
@@ -67,7 +69,7 @@ module AMQP
67
69
  end
68
70
  end
69
71
 
70
- def send data, opts = {}
72
+ def send(data, opts = {})
71
73
  channel = opts[:channel] ||= 0
72
74
  data = data.to_frame(channel) unless data.is_a? Frame
73
75
  data.channel = channel
@@ -81,8 +83,8 @@ module AMQP
81
83
  end
82
84
 
83
85
  private
84
-
85
- def log *args
86
+
87
+ def log(*args)
86
88
  require 'pp'
87
89
  pp args
88
90
  puts
@@ -93,7 +95,7 @@ end
93
95
  if __FILE__ == $0
94
96
  require 'rubygems'
95
97
  require 'eventmachine'
96
- EM.run{
98
+ EM.run {
97
99
  AMQP::Server.start
98
100
  }
99
- end
101
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
 
2
4
  #:stopdoc:
3
5
  # this file was autogenerated on Thu Jul 09 15:17:33 -0700 2009
@@ -76,7 +78,7 @@ module AMQP
76
78
  end
77
79
  ]
78
80
  end
79
-
81
+
80
82
  def properties() @properties ||= [] end
81
83
 
82
84
  def id() self::ID end
@@ -93,10 +95,10 @@ module AMQP
93
95
  end
94
96
  ]
95
97
  end
96
-
98
+
97
99
  def arguments() @arguments ||= [] end
98
100
 
99
- def section() Protocol.const_get(self.to_s[/Protocol::(.+?)::/,1]) end
101
+ def section() Protocol.const_get(self.to_s[/Protocol::(.+?)::/, 1]) end
100
102
  def id() self::ID end
101
103
  def name() self::NAME end
102
104
  end
@@ -107,9 +109,9 @@ module AMQP
107
109
  end
108
110
  end
109
111
  end
110
-
112
+
111
113
  def self.methods() @methods ||= {} end
112
-
114
+
113
115
  def self.Method(id, name)
114
116
  @_base_methods ||= {}
115
117
  @_base_methods[id] ||= ::Class.new(Method) do
@@ -142,7 +144,7 @@ module AMQP
142
144
  end
143
145
  end
144
146
  end
145
-
147
+
146
148
  module AMQP
147
149
  module Protocol
148
150
  class Connection < Class( 10, :connection ); end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module AMQP
2
4
  VERSION = '0.7.0'
3
5
  end
@@ -1,7 +1,9 @@
1
+ # encoding: utf-8
2
+
1
3
  unless defined?(BlankSlate)
2
4
  class BlankSlate < BasicObject; end if defined?(BasicObject)
3
5
 
4
6
  class BlankSlate #:nodoc:
5
7
  instance_methods.each { |m| undef_method m unless m =~ /^__/ }
6
8
  end
7
- end
9
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  begin
2
4
  require 'eventmachine'
3
5
  rescue LoadError
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  EMFORK = $0 == __FILE__
2
4
 
3
5
  if EMFORK
@@ -11,21 +13,21 @@ require 'eventmachine'
11
13
  # helper to fork off EM reactors
12
14
  def EM.fork num = 1, &blk
13
15
  unless @forks
14
- trap('CHLD'){
16
+ trap('CHLD') {
15
17
  pid = Process.wait
16
18
  p [:pid, pid, :died] if EMFORK
17
19
  block = @forks.delete(pid)
18
20
  EM.fork(1, &block)
19
21
  }
20
22
 
21
- trap('EXIT'){
23
+ trap('EXIT') {
22
24
  p [:pid, Process.pid, :exit] if EMFORK
23
- @forks.keys.each{ |pid|
25
+ @forks.keys.each { |pid|
24
26
  p [:pid, Process.pid, :killing, pid] if EMFORK
25
27
  Process.kill('USR1', pid)
26
28
  }
27
29
  }
28
-
30
+
29
31
  @forks = {}
30
32
  end
31
33
 
@@ -33,9 +35,9 @@ def EM.fork num = 1, &blk
33
35
  pid = EM.fork_reactor do
34
36
  p [:pid, Process.pid, :started] if EMFORK
35
37
 
36
- trap('USR1'){ EM.stop_event_loop }
37
- trap('CHLD'){}
38
- trap('EXIT'){}
38
+ trap('USR1') { EM.stop_event_loop }
39
+ trap('CHLD') {}
40
+ trap('EXIT') {}
39
41
 
40
42
  blk.call
41
43
  end
@@ -52,12 +54,12 @@ end
52
54
  if EMFORK
53
55
  p 'starting reactor'
54
56
 
55
- trap('INT'){ EM.stop_event_loop }
57
+ trap('INT') { EM.stop_event_loop }
56
58
 
57
- EM.run{
59
+ EM.run {
58
60
  p [:parent, Process.pid]
59
61
 
60
- EM.fork(2){
62
+ EM.fork(2) {
61
63
  EM.add_periodic_timer(1) do
62
64
  p [:fork, Process.pid, :ping]
63
65
  end
@@ -66,4 +68,4 @@ if EMFORK
66
68
  }
67
69
 
68
70
  p 'reactor stopped'
69
- end
71
+ end