amqp 0.7.0.pre → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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