amqp 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,4 +1,11 @@
1
- Simple AMQP driver for Ruby/EventMachine.
1
+ Simple AMQP driver for Ruby/EventMachine
2
+ (c) 2008 Aman Gupta (tmm1)
3
+
4
+ http://github.com/tmm1/amqp
5
+ http://rubyforge.org/projects/amqp
6
+ http://hopper.squarespace.com/blog/2008/7/22/simple-amqp-library-for-ruby.html
7
+ http://groups.google.com/group/ruby-amqp
8
+ http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-July/001417.html
2
9
 
3
10
  This library was tested primarily with RabbitMQ, although it should be compatible with any
4
11
  server implementing the AMQP 0-8 spec.
@@ -12,15 +19,17 @@ To use with RabbitMQ, first run the server:
12
19
 
13
20
  To get started, refer to the various bundled examples:
14
21
 
15
- ruby examples/pingpong.rb # 1-1 communication using amq.direct
16
- ruby examples/clock.rb # 1-N communication using amq.fanout
17
- ruby examples/stocks.rb # 1-subscriber communication using amq.topic
18
- ruby examples/hashtable.rb # simple async rpc layer
19
- ruby examples/primes.rb 4 # parallelized prime number generation
22
+ ruby examples/mq/simple.rb # low-level Queue/Exchange api
23
+ ruby examples/mq/pingpong.rb # 1-1 communication using amq.direct
24
+ ruby examples/mq/clock.rb # 1-N communication using amq.fanout
25
+ ruby examples/mq/stocks.rb # 1-subscriber communication using amq.topic
26
+ ruby examples/mq/hashtable.rb # simple async rpc layer
27
+ ruby examples/mq/primes.rb 4 # parallelized prime number generation
28
+ ruby examples/mq/logger.rb # simple logging api
20
29
 
21
30
  For more details into the lower level AMQP client API, run the simple client example:
22
31
 
23
- ruby examples/simple.rb
32
+ ruby examples/amqp/simple.rb # low-level AMQP api
24
33
 
25
34
  Or refer to protocol/doc.txt, which enumerates packets sent between a server and client
26
35
  during a typical session, in both binary and decoded formats.
@@ -36,32 +45,47 @@ The lib/amqp/spec.rb file is generated automatically based on the AMQP specifica
36
45
  This project was inspired by py-amqplib, rabbitmq, qpid and rubbyt.
37
46
  Special thanks to Dmitriy Samovskiy, Ben Hood and Tony Garnock-Jones.
38
47
 
39
- Other AMQP resources:
48
+ AMQP resources:
40
49
 
41
50
  Servers:
42
- RabbitMQ (Rabbit Technologies, Erlang/OTP, MPL) http://rabbitmq.com
43
- OpenAMP (iMatrix, C, GPL2) http://openamq.org
44
- ActiveMQ (Apache Foundation, Java, apache2) http://activemq.apache.org/
51
+ RabbitMQ (Rabbit Technologies, Erlang/OTP, MPL) - http://rabbitmq.com
52
+ ZeroMQ (iMatrix/FastMQ/Intel, C++, GPL3) - http://www.zeromq.org
53
+ OpenAMQ (iMatrix, C, GPL2) - http://openamq.org
54
+ ActiveMQ (Apache Foundation, Java, apache2) - http://activemq.apache.org/
45
55
 
46
- John O'Hara's article on the history of AMQP:
56
+ Steve Vinoski explains AMQP in his column, Towards Integration
57
+ http://steve.vinoski.net/pdf/IEEE-Advanced_Message_Queuing_Protocol.pdf
58
+
59
+ John O'Hara on the history of AMQP
47
60
  http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=485
48
61
 
49
- Barry Pederson's py-amqplib:
62
+ ZeroMQ's analysis of the messaging technology market
63
+ http://www.zeromq.org/whitepapers:market-analysis
64
+
65
+ ZeroMQ's background to AMQP
66
+ http://www.zeromq.org/whitepapers:amqp-analysis
67
+
68
+ Barry Pederson's py-amqplib
50
69
  http://barryp.org/software/py-amqplib/
51
70
 
52
- Ben Hood's article on writing an AMQP client:
71
+ Ben Hood on writing an AMQP client
53
72
  http://hopper.squarespace.com/blog/2008/6/21/build-your-own-amqp-client.html
54
73
 
55
- Dmitriy Samovskiy's introduction to Ruby+QPid+RabbitMQ:
74
+ Dmitriy Samovskiy introduces Ruby + QPid + RabbitMQ
56
75
  http://somic-org.homelinux.org/blog/2008/06/24/ruby-amqp-rabbitmq-example/
57
76
 
58
- Ben Hood's AMQP client in AS3:
77
+ Ben Hood's as3-amqp
59
78
  http://github.com/0x6e6562/as3-amqp
79
+ http://hopper.squarespace.com/blog/2008/7/4/server-side-as3.html
80
+ http://hopper.squarespace.com/blog/2008/3/24/as3-amqp-client-first-cut.html
60
81
 
61
- RabbitMQ's protocol code generator:
82
+ RabbitMQ's protocol code generator
62
83
  http://hg.rabbitmq.com/rabbitmq-codegen/
63
84
 
64
- Jonahthan Conway's series on RabbitMQ and using it with Ruby/Merb:
85
+ Erlang Exchange presentation on the implementation of RabbitMQ
86
+ http://www.lshift.net/blog/2008/07/01/slides-from-our-erlang-exchange-talk
87
+
88
+ Jonathan Conway's series on RabbitMQ and using it with Ruby/Merb
65
89
  http://jaikoo.com/2008/3/20/daemonize-rabbitmq
66
90
  http://jaikoo.com/2008/3/14/oh-hai-rabbitmq
67
91
  http://jaikoo.com/2008/2/29/friday-round-up-2008-02-29
@@ -77,3 +101,9 @@ Messaging and distributed systems resources:
77
101
 
78
102
  Convenience Over Correctness
79
103
  http://steve.vinoski.net/pdf/IEEE-Convenience_Over_Correctness.pdf
104
+
105
+ Metaprotocol Taxonomy and Communications Patterns
106
+ http://hessian.caucho.com/doc/metaprotocol-taxonomy.xtp
107
+
108
+ Joe Armstrong on Erlang messaging vs RPC:
109
+ http://armstrongonsoftware.blogspot.com/2008/05/road-we-didnt-go-down.html
@@ -1,4 +1,4 @@
1
- $:.unshift File.dirname(__FILE__) + '/../lib'
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'amqp'
3
3
 
4
4
  module SimpleClient
@@ -1,4 +1,4 @@
1
- $:.unshift File.dirname(__FILE__) + '/../lib'
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'mq'
3
3
 
4
4
  EM.run{
@@ -1,4 +1,4 @@
1
- $:.unshift File.dirname(__FILE__) + '/../lib'
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'mq'
3
3
 
4
4
  EM.run{
@@ -0,0 +1,139 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
+ require 'mq'
3
+
4
+ class Logger
5
+ def initialize *args, &block
6
+ opts = args.pop if args.last.is_a? Hash
7
+ opts ||= {}
8
+ printer(block) if block
9
+ @log = []
10
+ @tags = ([:timestamp] + args).uniq
11
+ end
12
+
13
+ def log severity, *args
14
+ opts = args.pop if args.last.is_a? Hash and args.size != 1
15
+ opts ||= {}
16
+ data = args.shift
17
+
18
+ data = {:type => :exception,
19
+ :name => data.class.to_s.intern,
20
+ :backtrace => data.backtrace,
21
+ :message => data.message} if data.is_a? Exception
22
+
23
+ (@tags + args).each do |tag|
24
+ tag = tag.to_sym
25
+ case tag
26
+ when :timestamp
27
+ opts.update :timestamp => Time.now.to_i
28
+ when :hostname
29
+ @hostname ||= { :hostname => `hostname`.strip }
30
+ opts.update @hostname
31
+ when :process
32
+ @process_id ||= { :process_id => Process.pid,
33
+ :process_name => $0,
34
+ :process_parent_id => Process.ppid,
35
+ :thread_id => Thread.current.object_id }
36
+ opts.update :process => @process_id
37
+ else
38
+ (opts[:tags] ||= []) << tag
39
+ end
40
+ end
41
+
42
+ opts.update(:severity => severity,
43
+ :data => data)
44
+
45
+ print(opts)
46
+ MQ.queue('logger', :durable => true).publish(Marshal.dump(opts), :persistent => true)
47
+ opts
48
+ end
49
+ alias :method_missing :log
50
+
51
+ def print data = nil, &block
52
+ if block
53
+ @printer = block
54
+ elsif data.is_a? Proc
55
+ @printer = data
56
+ elsif @printer and data
57
+ @printer.call(data)
58
+ else
59
+ @printer
60
+ end
61
+ end
62
+ alias :printer :print
63
+ end
64
+
65
+ EM.run{
66
+ # AMQP.logging = true
67
+ # MQ.logging = true
68
+
69
+ if ARGV[0] == 'server'
70
+
71
+ MQ.queue('logger', :durable => true).subscribe{|msg|
72
+ msg = Marshal.load(msg)
73
+ require 'pp'
74
+ pp(msg)
75
+ puts
76
+ }
77
+
78
+ else
79
+
80
+ log = Logger.new
81
+ log.debug 'its working!'
82
+
83
+ log = Logger.new do |msg|
84
+ require 'pp'
85
+ pp msg
86
+ puts
87
+ end
88
+
89
+ log.info '123'
90
+ log.debug [1,2,3]
91
+ log.debug :one => 1, :two => 2
92
+ log.error Exception.new('123')
93
+
94
+ log.info '123', :process_id => Process.pid
95
+ log.info '123', :process
96
+ log.debug 'login', :session => 'abc', :user => 123
97
+
98
+ log = Logger.new(:webserver, :timestamp, :hostname, &log.printer)
99
+ log.info 'Request for /', :GET, :session => 'abc'
100
+
101
+ AMQP.stop
102
+
103
+ end
104
+ }
105
+
106
+ __END__
107
+
108
+ {:data=>"123", :timestamp=>1216846102, :severity=>:info}
109
+
110
+ {:data=>[1, 2, 3], :timestamp=>1216846102, :severity=>:debug}
111
+
112
+ {:data=>
113
+ {:type=>:exception, :name=>:Exception, :message=>"123", :backtrace=>nil},
114
+ :timestamp=>1216846102,
115
+ :severity=>:error}
116
+
117
+ {:data=>"123", :timestamp=>1216846102, :process_id=>1814, :severity=>:info}
118
+
119
+ {:process=>
120
+ {:thread_id=>109440,
121
+ :process_id=>1814,
122
+ :process_name=>"/Users/aman/code/amqp/examples/logger.rb",
123
+ :process_parent_id=>1813},
124
+ :data=>"123",
125
+ :timestamp=>1216846102,
126
+ :severity=>:info}
127
+
128
+ {:session=>"abc",
129
+ :data=>"login",
130
+ :timestamp=>1216846102,
131
+ :severity=>:debug,
132
+ :user=>123}
133
+
134
+ {:session=>"abc",
135
+ :tags=>[:webserver, :GET],
136
+ :data=>"Request for /",
137
+ :timestamp=>1216846102,
138
+ :severity=>:info,
139
+ :hostname=>"gc"}
@@ -1,4 +1,4 @@
1
- $:.unshift File.dirname(__FILE__) + '/../lib'
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'mq'
3
3
 
4
4
  EM.run{
@@ -1,4 +1,4 @@
1
- $:.unshift File.dirname(__FILE__) + '/../lib'
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'mq'
3
3
 
4
4
  # check MAX numbers for prime-ness
@@ -0,0 +1,41 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
+ require 'mq'
3
+ require 'pp'
4
+
5
+ EM.run do
6
+
7
+ # open a channel on the AMQP connection
8
+ channel = MQ.new
9
+
10
+ # declare a queue on the channel
11
+ queue = MQ::Queue.new(channel, 'queue name')
12
+
13
+ # use the default fanout exchange
14
+ exchange = MQ::Exchange.new(channel, :fanout, 'all queues')
15
+
16
+ # bind the queue to the exchange
17
+ queue.bind(exchange)
18
+
19
+ # publish a message to the exchange
20
+ exchange.publish('hello world')
21
+
22
+ # subscribe to messages from the queue
23
+ queue.subscribe do |headers, msg|
24
+ pp [:got, headers, msg]
25
+ AMQP.stop
26
+ end
27
+
28
+ end
29
+
30
+ __END__
31
+
32
+ [:got,
33
+ #<AMQP::Protocol::Header:0x118a438
34
+ @klass=AMQP::Protocol::Basic,
35
+ @properties=
36
+ {:priority=>0,
37
+ :delivery_mode=>1,
38
+ :content_type=>"application/octet-stream"},
39
+ @size=11,
40
+ @weight=0>,
41
+ "hello world"]
@@ -1,4 +1,4 @@
1
- $:.unshift File.dirname(__FILE__) + '/../lib'
1
+ $:.unshift File.dirname(__FILE__) + '/../../lib'
2
2
  require 'mq'
3
3
 
4
4
  EM.run{
@@ -1,9 +1,11 @@
1
1
  module AMQP
2
+ VERSION = '0.5.3'
3
+
2
4
  DIR = File.expand_path(File.dirname(File.expand_path(__FILE__)))
3
-
4
5
  $:.unshift DIR
5
6
 
6
7
  require 'ext/em'
8
+ require 'ext/blankslate'
7
9
 
8
10
  %w[ buffer spec protocol frame client ].each do |file|
9
11
  require "amqp/#{file}"
@@ -12,5 +14,42 @@ module AMQP
12
14
  class << self
13
15
  @logging = false
14
16
  attr_accessor :logging
17
+ attr_reader :stopping
18
+ end
19
+
20
+ def self.settings
21
+ @settings ||= {
22
+ :user => 'guest',
23
+ :pass => 'guest',
24
+ :vhost => '/'
25
+ }
26
+ end
27
+
28
+ def self.start *args
29
+ @conn ||= Client.connect *args
30
+ end
31
+
32
+ def self.stop stop_reactor = true, &on_stop
33
+ if @conn
34
+ @conn.callback{ |c|
35
+ if c.channels.keys.any?
36
+ c.channels.each do |_, mq|
37
+ mq.close
38
+ end
39
+ else
40
+ c.close
41
+ end
42
+ }
43
+ @on_stop = proc{
44
+ @conn = nil
45
+ on_stop.call if on_stop
46
+ EM.stop_event_loop if stop_reactor
47
+ }
48
+ end
49
+ end
50
+
51
+ def self.stopped
52
+ @on_stop.call if @on_stop
53
+ @on_stop = nil
15
54
  end
16
55
  end
@@ -1,7 +1,8 @@
1
1
  require 'amqp/frame'
2
- require 'pp'
3
2
 
4
3
  module AMQP
4
+ class Error < Exception; end
5
+
5
6
  module BasicClient
6
7
  def process_frame frame
7
8
  if mq = channels[frame.channel]
@@ -16,10 +17,10 @@ module AMQP
16
17
  send Protocol::Connection::StartOk.new({:platform => 'Ruby/EventMachine',
17
18
  :product => 'AMQP',
18
19
  :information => 'http://github.com/tmm1/amqp',
19
- :version => '0.5.0'},
20
+ :version => VERSION},
20
21
  'AMQPLAIN',
21
- {:LOGIN => 'guest',
22
- :PASSWORD => 'guest'},
22
+ {:LOGIN => @settings[:user],
23
+ :PASSWORD => @settings[:pass]},
23
24
  'en_US')
24
25
 
25
26
  when Protocol::Connection::Tune
@@ -27,12 +28,18 @@ module AMQP
27
28
  :frame_max => 131072,
28
29
  :heartbeat => 0)
29
30
 
30
- send Protocol::Connection::Open.new(:virtual_host => '/',
31
+ send Protocol::Connection::Open.new(:virtual_host => @settings[:vhost],
31
32
  :capabilities => '',
32
33
  :insist => false)
33
34
 
34
35
  when Protocol::Connection::OpenOk
35
36
  @dfr.succeed(self)
37
+
38
+ when Protocol::Connection::Close
39
+ raise Error, "#{method.reply_text} in #{Protocol.classes[method.class_id].methods[method.method_id]}"
40
+
41
+ when Protocol::Connection::CloseOk
42
+ AMQP.stopped
36
43
  end
37
44
  end
38
45
  end
@@ -48,8 +55,9 @@ module AMQP
48
55
  end
49
56
 
50
57
  module Client
51
- def initialize dfr
58
+ def initialize dfr, opts = {}
52
59
  @dfr = dfr
60
+ @settings = opts
53
61
  extend AMQP.client
54
62
  end
55
63
 
@@ -70,8 +78,8 @@ module AMQP
70
78
  end
71
79
 
72
80
  def receive_data data
81
+ # log 'receive_data', data
73
82
  @buf << data
74
- log 'receive_data', data
75
83
 
76
84
  while frame = Frame.parse(@buf)
77
85
  log 'receive', frame
@@ -92,9 +100,16 @@ module AMQP
92
100
  send_data data.to_s
93
101
  end
94
102
 
95
- def send_data data
96
- log 'send_data', data
97
- super
103
+ # def send_data data
104
+ # log 'send_data', data
105
+ # super
106
+ # end
107
+
108
+ def close
109
+ send Protocol::Connection::Close.new(:reply_code => 200,
110
+ :reply_text => 'Goodbye',
111
+ :class_id => 0,
112
+ :method_id => 0)
98
113
  end
99
114
 
100
115
  def unbind
@@ -102,13 +117,14 @@ module AMQP
102
117
  end
103
118
 
104
119
  def self.connect opts = {}
120
+ opts = AMQP.settings.merge(opts)
105
121
  opts[:host] ||= 'localhost'
106
122
  opts[:port] ||= PORT
107
123
 
108
124
  dfr = EM::DefaultDeferrable.new
109
125
 
110
126
  EM.run{
111
- EM.connect opts[:host], opts[:port], self, dfr
127
+ EM.connect opts[:host], opts[:port], self, dfr, opts
112
128
  }
113
129
 
114
130
  dfr
@@ -118,16 +134,9 @@ module AMQP
118
134
 
119
135
  def log *args
120
136
  return unless AMQP.logging
137
+ require 'pp'
121
138
  pp args
122
139
  puts
123
140
  end
124
141
  end
125
-
126
- def self.start *args
127
- @conn ||= Client.connect *args
128
- end
129
- end
130
-
131
- if $0 == __FILE__
132
- AMQP.start
133
142
  end
@@ -23,6 +23,12 @@ module AMQP
23
23
  end
24
24
  end
25
25
 
26
+ def arguments
27
+ self.class.arguments.inject({}) do |hash, (type, name)|
28
+ hash.update name => instance_variable_get("@#{name}")
29
+ end
30
+ end
31
+
26
32
  def to_binary
27
33
  buf = Buffer.new
28
34
  buf.write :short, self.class.parent.id
@@ -116,8 +122,8 @@ module AMQP
116
122
  end
117
123
 
118
124
  def method_missing meth, *args, &blk
119
- @klass.properties.map{|_,name| name }.include?(meth) ? @properties[meth] :
120
- super
125
+ @properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] :
126
+ super
121
127
  end
122
128
  end
123
129
 
@@ -0,0 +1,7 @@
1
+ unless defined?(BlankSlate)
2
+ class BlankSlate < BasicObject; end if defined?(BasicObject)
3
+
4
+ class BlankSlate
5
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
6
+ end
7
+ end
data/lib/mq.rb CHANGED
@@ -10,6 +10,8 @@ class MQ
10
10
  @logging = false
11
11
  attr_accessor :logging
12
12
  end
13
+
14
+ class Error < Exception; end
13
15
  end
14
16
 
15
17
  class MQ
@@ -35,6 +37,7 @@ class MQ
35
37
  when Frame::Body
36
38
  @body << frame.payload
37
39
  if @body.length >= @header.size
40
+ @header.properties.update(@method.arguments)
38
41
  @consumer.receive @header, @body
39
42
  @body = ''
40
43
  end
@@ -49,12 +52,30 @@ class MQ
49
52
 
50
53
  when Protocol::Access::RequestOk
51
54
  @ticket = method.ticket
55
+ callback{
56
+ send Protocol::Channel::Close.new(:reply_code => 200,
57
+ :reply_text => 'bye',
58
+ :method_id => 0,
59
+ :class_id => 0)
60
+ } if @closing
52
61
  succeed
53
62
 
54
63
  when Protocol::Basic::Deliver
64
+ @method = method
55
65
  @header = nil
56
66
  @body = ''
57
67
  @consumer = queues[ method.consumer_tag ]
68
+
69
+
70
+ when Protocol::Channel::Close
71
+ raise Error, "#{method.reply_text} in #{Protocol.classes[method.class_id].methods[method.method_id]}"
72
+
73
+ when Protocol::Channel::CloseOk
74
+ @closing = false
75
+ conn.callback{ |c|
76
+ c.channels.delete(@channel)
77
+ c.close unless c.channels.keys.any?
78
+ }
58
79
  end
59
80
  end
60
81
  end
@@ -83,12 +104,15 @@ class MQ
83
104
  rpcs[name] ||= RPC.new(self, name, obj)
84
105
  end
85
106
 
86
- private
87
-
88
- def log *args
89
- return unless MQ.logging
90
- pp args
91
- puts
107
+ def close
108
+ if @deferred_status == :succeeded
109
+ send Protocol::Channel::Close.new(:reply_code => 200,
110
+ :reply_text => 'bye',
111
+ :method_id => 0,
112
+ :class_id => 0)
113
+ else
114
+ @closing = true
115
+ end
92
116
  end
93
117
 
94
118
  # keep track of proxy objects
@@ -105,9 +129,18 @@ class MQ
105
129
  @rcps ||= {}
106
130
  end
107
131
 
132
+ private
133
+
134
+ def log *args
135
+ return unless MQ.logging
136
+ pp args
137
+ puts
138
+ end
139
+
108
140
  # create a class level connection on demand
109
141
 
110
142
  def connection
143
+ raise 'MQ can only be used within EM.run{}' unless EM.reactor_running?
111
144
  @@connection ||= AMQP.start
112
145
  end
113
146
  alias :conn :connection
@@ -5,6 +5,7 @@ class MQ
5
5
  def initialize mq, type, name, opts = {}
6
6
  @mq = mq
7
7
  @type, @name = type, name
8
+ @mq.exchanges[@name = name] ||= self
8
9
  @key = opts[:key]
9
10
 
10
11
  @mq.callback{
@@ -17,18 +18,16 @@ class MQ
17
18
 
18
19
  def publish data, opts = {}
19
20
  @mq.callback{
20
- EM.next_tick do
21
- @mq.send Protocol::Basic::Publish.new({ :exchange => name,
22
- :routing_key => opts.delete(:key) || @key }.merge(opts))
23
-
24
- data = data.to_s
21
+ @mq.send Protocol::Basic::Publish.new({ :exchange => name,
22
+ :routing_key => opts.delete(:key) || @key }.merge(opts))
23
+
24
+ data = data.to_s
25
25
 
26
- @mq.send Protocol::Header.new(Protocol::Basic,
27
- data.length, { :content_type => 'application/octet-stream',
28
- :delivery_mode => 1,
29
- :priority => 0 }.merge(opts))
30
- @mq.send Frame::Body.new(data)
31
- end
26
+ @mq.send Protocol::Header.new(Protocol::Basic,
27
+ data.length, { :content_type => 'application/octet-stream',
28
+ :delivery_mode => (opts.delete(:persistent) ? 2 : 1),
29
+ :priority => 0 }.merge(opts))
30
+ @mq.send Frame::Body.new(data)
32
31
  }
33
32
  self
34
33
  end
@@ -4,7 +4,7 @@ class MQ
4
4
 
5
5
  def initialize mq, name, opts = {}
6
6
  @mq = mq
7
- @name = name
7
+ @mq.queues[@name = name] ||= self
8
8
  @mq.callback{
9
9
  @mq.send Protocol::Queue::Declare.new({ :queue => name,
10
10
  :nowait => true }.merge(opts))
@@ -1,15 +1,8 @@
1
- unless defined?(BlankSlate)
2
- class BlankSlate < BasicObject; end if defined?(BasicObject)
3
-
4
- class BlankSlate
5
- instance_methods.each { |m| undef_method m unless m =~ /^__/ }
6
- end
7
- end
8
-
9
1
  class MQ
10
2
  class RPC < BlankSlate
11
3
  def initialize mq, queue, obj = nil
12
4
  @mq = mq
5
+ @mq.rpcs[queue] ||= self
13
6
 
14
7
  if obj
15
8
  @obj = case obj
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amqp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aman Gupta
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-22 00:00:00 -07:00
12
+ date: 2008-07-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,19 +32,22 @@ extra_rdoc_files: []
32
32
 
33
33
  files:
34
34
  - README
35
- - examples/clock.rb
36
- - examples/hashtable.rb
37
- - examples/pingpong.rb
38
- - examples/primes-simple.rb
39
- - examples/primes.rb
40
- - examples/simple.rb
41
- - examples/stocks.rb
35
+ - examples/amqp/simple.rb
36
+ - examples/mq/clock.rb
37
+ - examples/mq/hashtable.rb
38
+ - examples/mq/logger.rb
39
+ - examples/mq/pingpong.rb
40
+ - examples/mq/primes-simple.rb
41
+ - examples/mq/primes.rb
42
+ - examples/mq/simple.rb
43
+ - examples/mq/stocks.rb
42
44
  - lib/amqp/buffer.rb
43
45
  - lib/amqp/client.rb
44
46
  - lib/amqp/frame.rb
45
47
  - lib/amqp/protocol.rb
46
48
  - lib/amqp/spec.rb
47
49
  - lib/amqp.rb
50
+ - lib/ext/blankslate.rb
48
51
  - lib/ext/em.rb
49
52
  - lib/ext/emfork.rb
50
53
  - lib/mq/exchange.rb