amqp 0.5.2 → 0.5.3
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/README +48 -18
- data/examples/{simple.rb → amqp/simple.rb} +1 -1
- data/examples/{clock.rb → mq/clock.rb} +1 -1
- data/examples/{hashtable.rb → mq/hashtable.rb} +1 -1
- data/examples/mq/logger.rb +139 -0
- data/examples/{pingpong.rb → mq/pingpong.rb} +1 -1
- data/examples/{primes-simple.rb → mq/primes-simple.rb} +0 -0
- data/examples/{primes.rb → mq/primes.rb} +1 -1
- data/examples/mq/simple.rb +41 -0
- data/examples/{stocks.rb → mq/stocks.rb} +1 -1
- data/lib/amqp.rb +40 -1
- data/lib/amqp/client.rb +28 -19
- data/lib/amqp/protocol.rb +8 -2
- data/lib/ext/blankslate.rb +7 -0
- data/lib/mq.rb +39 -6
- data/lib/mq/exchange.rb +10 -11
- data/lib/mq/queue.rb +1 -1
- data/lib/mq/rpc.rb +1 -8
- metadata +12 -9
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/
|
16
|
-
ruby examples/
|
17
|
-
ruby examples/
|
18
|
-
ruby examples/
|
19
|
-
ruby examples/
|
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
|
-
|
48
|
+
AMQP resources:
|
40
49
|
|
41
50
|
Servers:
|
42
|
-
RabbitMQ (Rabbit Technologies, Erlang/OTP, MPL)
|
43
|
-
|
44
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
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
|
@@ -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"}
|
File without changes
|
@@ -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"]
|
data/lib/amqp.rb
CHANGED
@@ -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
|
data/lib/amqp/client.rb
CHANGED
@@ -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 =>
|
20
|
+
:version => VERSION},
|
20
21
|
'AMQPLAIN',
|
21
|
-
{:LOGIN =>
|
22
|
-
:PASSWORD =>
|
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
|
-
|
97
|
-
|
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
|
data/lib/amqp/protocol.rb
CHANGED
@@ -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.
|
120
|
-
|
125
|
+
@properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] :
|
126
|
+
super
|
121
127
|
end
|
122
128
|
end
|
123
129
|
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
data/lib/mq/exchange.rb
CHANGED
@@ -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
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
data/lib/mq/queue.rb
CHANGED
data/lib/mq/rpc.rb
CHANGED
@@ -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.
|
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-
|
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/
|
36
|
-
- examples/
|
37
|
-
- examples/
|
38
|
-
- examples/
|
39
|
-
- examples/
|
40
|
-
- examples/simple.rb
|
41
|
-
- examples/
|
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
|