adamh-amqp 0.6.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +128 -0
- data/Rakefile +15 -0
- data/amqp.gemspec +83 -0
- data/amqp.todo +32 -0
- data/doc/EXAMPLE_01_PINGPONG +2 -0
- data/doc/EXAMPLE_02_CLOCK +2 -0
- data/doc/EXAMPLE_03_STOCKS +2 -0
- data/doc/EXAMPLE_04_MULTICLOCK +2 -0
- data/doc/EXAMPLE_05_ACK +2 -0
- data/doc/EXAMPLE_05_POP +2 -0
- data/doc/EXAMPLE_06_HASHTABLE +2 -0
- data/examples/amqp/simple.rb +79 -0
- data/examples/mq/ack.rb +45 -0
- data/examples/mq/clock.rb +56 -0
- data/examples/mq/hashtable.rb +52 -0
- data/examples/mq/internal.rb +49 -0
- data/examples/mq/logger.rb +88 -0
- data/examples/mq/multiclock.rb +49 -0
- data/examples/mq/pingpong.rb +45 -0
- data/examples/mq/pop.rb +43 -0
- data/examples/mq/primes-simple.rb +19 -0
- data/examples/mq/primes.rb +99 -0
- data/examples/mq/stocks.rb +58 -0
- data/lib/amqp.rb +115 -0
- data/lib/amqp/buffer.rb +395 -0
- data/lib/amqp/client.rb +210 -0
- data/lib/amqp/frame.rb +124 -0
- data/lib/amqp/protocol.rb +212 -0
- data/lib/amqp/server.rb +99 -0
- data/lib/amqp/spec.rb +832 -0
- data/lib/ext/blankslate.rb +7 -0
- data/lib/ext/em.rb +51 -0
- data/lib/ext/emfork.rb +69 -0
- data/lib/mq.rb +823 -0
- data/lib/mq/exchange.rb +302 -0
- data/lib/mq/header.rb +33 -0
- data/lib/mq/logger.rb +89 -0
- data/lib/mq/queue.rb +433 -0
- data/lib/mq/rpc.rb +100 -0
- data/old/README +30 -0
- data/old/Rakefile +12 -0
- data/old/amqp-0.8.json +606 -0
- data/old/amqp_spec.rb +796 -0
- data/old/amqpc.rb +695 -0
- data/old/codegen.rb +148 -0
- data/protocol/amqp-0.8.json +617 -0
- data/protocol/amqp-0.8.xml +3908 -0
- data/protocol/codegen.rb +173 -0
- data/protocol/doc.txt +281 -0
- data/research/api.rb +88 -0
- data/research/primes-forked.rb +63 -0
- data/research/primes-processes.rb +135 -0
- data/research/primes-threaded.rb +49 -0
- metadata +121 -0
data/README
ADDED
@@ -0,0 +1,128 @@
|
|
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
|
9
|
+
|
10
|
+
This library works with Ruby 1.8, Ruby 1.9 and JRuby.
|
11
|
+
|
12
|
+
This library was tested primarily with RabbitMQ, although it should be compatible with any
|
13
|
+
server implementing the AMQP 0-8 spec.
|
14
|
+
|
15
|
+
To use with RabbitMQ, first run the server:
|
16
|
+
|
17
|
+
hg clone http://hg.rabbitmq.com/rabbitmq-codegen
|
18
|
+
hg clone http://hg.rabbitmq.com/rabbitmq-server
|
19
|
+
cd rabbitmq-server
|
20
|
+
make run
|
21
|
+
|
22
|
+
To get started, refer to the various bundled examples:
|
23
|
+
|
24
|
+
ruby examples/mq/pingpong.rb # 1-1 communication using amq.direct
|
25
|
+
ruby examples/mq/clock.rb # 1-N communication using amq.fanout
|
26
|
+
ruby examples/mq/stocks.rb # 1-subscriber communication using amq.topic
|
27
|
+
|
28
|
+
ruby examples/mq/multiclock.rb # header based routing (new rabbitmq feature)
|
29
|
+
ruby examples/mq/ack.rb # using ack
|
30
|
+
ruby examples/mq/pop.rb # pop off messages one at a time
|
31
|
+
|
32
|
+
ruby examples/mq/hashtable.rb # simple async rpc layer
|
33
|
+
ruby examples/mq/primes.rb 4 # parallelized prime number generation
|
34
|
+
ruby examples/mq/logger.rb # simple logging api
|
35
|
+
|
36
|
+
For more details into the lower level AMQP client API, run the simple client example:
|
37
|
+
|
38
|
+
ruby examples/amqp/simple.rb # low-level AMQP api
|
39
|
+
ruby examples/mq/internal.rb # low-level Queue/Exchange api
|
40
|
+
|
41
|
+
Or refer to protocol/doc.txt, which enumerates packets sent between a server and client
|
42
|
+
during a typical session, in both binary and decoded formats.
|
43
|
+
|
44
|
+
To run the test suite:
|
45
|
+
|
46
|
+
rake spec
|
47
|
+
|
48
|
+
The lib/amqp/spec.rb file is generated automatically based on the AMQP specification. To generate it:
|
49
|
+
|
50
|
+
rake codegen
|
51
|
+
|
52
|
+
This project was inspired by py-amqplib, rabbitmq, qpid and rubbyt.
|
53
|
+
Special thanks to Dmitriy Samovskiy, Ben Hood and Tony Garnock-Jones.
|
54
|
+
|
55
|
+
AMQP resources:
|
56
|
+
|
57
|
+
Servers:
|
58
|
+
RabbitMQ (Rabbit Technologies, Erlang/OTP, MPL) - http://rabbitmq.com
|
59
|
+
ZeroMQ (iMatix/FastMQ/Intel, C++, GPL3) - http://www.zeromq.org
|
60
|
+
OpenAMQ (iMatix, C, GPL2) - http://openamq.org
|
61
|
+
ActiveMQ (Apache Foundation, Java, apache2) - http://activemq.apache.org
|
62
|
+
|
63
|
+
Steve Vinoski explains AMQP in his column, Towards Integration
|
64
|
+
http://steve.vinoski.net/pdf/IEEE-Advanced_Message_Queuing_Protocol.pdf
|
65
|
+
|
66
|
+
John O'Hara on the history of AMQP
|
67
|
+
http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=485
|
68
|
+
|
69
|
+
Dmitriy's presentation on RabbitMQ/AMQP
|
70
|
+
http://somic-org.homelinux.org/blog/2008/07/31/slides-for-my-amqprabbitmq-talk/
|
71
|
+
|
72
|
+
ZeroMQ's analysis of the messaging technology market
|
73
|
+
http://www.zeromq.org/whitepapers:market-analysis
|
74
|
+
|
75
|
+
Pieter Hintjens's background to AMQP
|
76
|
+
http://www.openamq.org/doc:amqp-background
|
77
|
+
|
78
|
+
Barry Pederson's py-amqplib
|
79
|
+
http://barryp.org/software/py-amqplib/
|
80
|
+
|
81
|
+
Ben Hood on writing an AMQP client
|
82
|
+
http://hopper.squarespace.com/blog/2008/6/21/build-your-own-amqp-client.html
|
83
|
+
|
84
|
+
Dmitriy Samovskiy introduces Ruby + QPid + RabbitMQ
|
85
|
+
http://somic-org.homelinux.org/blog/2008/06/24/ruby-amqp-rabbitmq-example/
|
86
|
+
|
87
|
+
Ben Hood's as3-amqp
|
88
|
+
http://github.com/0x6e6562/as3-amqp
|
89
|
+
http://hopper.squarespace.com/blog/2008/7/4/server-side-as3.html
|
90
|
+
http://hopper.squarespace.com/blog/2008/3/24/as3-amqp-client-first-cut.html
|
91
|
+
|
92
|
+
RabbitMQ's protocol code generator
|
93
|
+
http://hg.rabbitmq.com/rabbitmq-codegen/
|
94
|
+
|
95
|
+
Erlang Exchange presentation on the implementation of RabbitMQ
|
96
|
+
http://skillsmatter.com/podcast/erlang/presenting-rabbitmq-an-erlang-based-implementatio-nof-amqp
|
97
|
+
http://www.lshift.net/blog/2008/07/01/slides-from-our-erlang-exchange-talk
|
98
|
+
|
99
|
+
Jonathan Conway's series on RabbitMQ and using it with Ruby/Merb
|
100
|
+
http://jaikoo.com/2008/3/20/daemonize-rabbitmq
|
101
|
+
http://jaikoo.com/2008/3/14/oh-hai-rabbitmq
|
102
|
+
http://jaikoo.com/2008/2/29/friday-round-up-2008-02-29
|
103
|
+
http://jaikoo.com/2007/9/4/didn-t-you-get-the-memo
|
104
|
+
|
105
|
+
Open Enterprise's series on messaging middleware and AMQP
|
106
|
+
http://www1.interopsystems.com/analysis/can-amqp-break-ibms-mom-monopoly-part-1.html
|
107
|
+
http://www1.interopsystems.com/analysis/can-amqp-break-ibms-mom-monopoly-part-2.html
|
108
|
+
http://www1.interopsystems.com/analysis/can-amqp-break-ibms-mom-monopoly-part-3.html
|
109
|
+
|
110
|
+
Messaging and distributed systems resources:
|
111
|
+
|
112
|
+
A Critique of the Remote Procedure Call Paradigm
|
113
|
+
http://www.cs.vu.nl/~ast/publications/euteco-1988.pdf
|
114
|
+
|
115
|
+
A Note on Distributed Computing
|
116
|
+
http://research.sun.com/techrep/1994/smli_tr-94-29.pdf
|
117
|
+
|
118
|
+
Convenience Over Correctness
|
119
|
+
http://steve.vinoski.net/pdf/IEEE-Convenience_Over_Correctness.pdf
|
120
|
+
|
121
|
+
Metaprotocol Taxonomy and Communications Patterns
|
122
|
+
http://hessian.caucho.com/doc/metaprotocol-taxonomy.xtp
|
123
|
+
|
124
|
+
Joe Armstrong on Erlang messaging vs RPC
|
125
|
+
http://armstrongonsoftware.blogspot.com/2008/05/road-we-didnt-go-down.html
|
126
|
+
|
127
|
+
SEDA: scalable internet services using message queues
|
128
|
+
http://www.eecs.harvard.edu/~mdw/papers/seda-sosp01.pdf
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
task :codegen do
|
2
|
+
sh 'ruby protocol/codegen.rb > lib/amqp/spec.rb'
|
3
|
+
sh 'ruby lib/amqp/spec.rb'
|
4
|
+
end
|
5
|
+
|
6
|
+
task :spec do
|
7
|
+
sh 'bacon lib/amqp.rb'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :gem do
|
11
|
+
sh 'gem build *.gemspec'
|
12
|
+
end
|
13
|
+
|
14
|
+
task :pkg => :gem
|
15
|
+
task :package => :gem
|
data/amqp.gemspec
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'amqp'
|
3
|
+
s.version = '0.6.3.1'
|
4
|
+
s.date = '2009-01-09'
|
5
|
+
s.summary = 'AMQP client implementation in Ruby/EventMachine'
|
6
|
+
s.email = "amqp@tmm1.net"
|
7
|
+
s.homepage = "http://amqp.rubyforge.org/"
|
8
|
+
s.description = "AMQP client implementation in Ruby/EventMachine"
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.rdoc_options = '--include=examples'
|
11
|
+
|
12
|
+
# ruby -rpp -e' pp `git ls-files`.split("\n").grep(/^(doc|README)/) '
|
13
|
+
s.extra_rdoc_files = [
|
14
|
+
"README",
|
15
|
+
"doc/EXAMPLE_01_PINGPONG",
|
16
|
+
"doc/EXAMPLE_02_CLOCK",
|
17
|
+
"doc/EXAMPLE_03_STOCKS",
|
18
|
+
"doc/EXAMPLE_04_MULTICLOCK",
|
19
|
+
"doc/EXAMPLE_05_ACK",
|
20
|
+
"doc/EXAMPLE_05_POP",
|
21
|
+
"doc/EXAMPLE_06_HASHTABLE"
|
22
|
+
]
|
23
|
+
|
24
|
+
s.authors = ["Aman Gupta"]
|
25
|
+
s.add_dependency('eventmachine', '>= 0.12.4')
|
26
|
+
|
27
|
+
# ruby -rpp -e' pp `git ls-files`.split("\n") '
|
28
|
+
s.files = [
|
29
|
+
"README",
|
30
|
+
"Rakefile",
|
31
|
+
"amqp.gemspec",
|
32
|
+
"amqp.todo",
|
33
|
+
"doc/EXAMPLE_01_PINGPONG",
|
34
|
+
"doc/EXAMPLE_02_CLOCK",
|
35
|
+
"doc/EXAMPLE_03_STOCKS",
|
36
|
+
"doc/EXAMPLE_04_MULTICLOCK",
|
37
|
+
"doc/EXAMPLE_05_ACK",
|
38
|
+
"doc/EXAMPLE_05_POP",
|
39
|
+
"doc/EXAMPLE_06_HASHTABLE",
|
40
|
+
"examples/amqp/simple.rb",
|
41
|
+
"examples/mq/ack.rb",
|
42
|
+
"examples/mq/clock.rb",
|
43
|
+
"examples/mq/pop.rb",
|
44
|
+
"examples/mq/hashtable.rb",
|
45
|
+
"examples/mq/internal.rb",
|
46
|
+
"examples/mq/logger.rb",
|
47
|
+
"examples/mq/multiclock.rb",
|
48
|
+
"examples/mq/pingpong.rb",
|
49
|
+
"examples/mq/primes-simple.rb",
|
50
|
+
"examples/mq/primes.rb",
|
51
|
+
"examples/mq/stocks.rb",
|
52
|
+
"lib/amqp.rb",
|
53
|
+
"lib/amqp/buffer.rb",
|
54
|
+
"lib/amqp/client.rb",
|
55
|
+
"lib/amqp/frame.rb",
|
56
|
+
"lib/amqp/protocol.rb",
|
57
|
+
"lib/amqp/server.rb",
|
58
|
+
"lib/amqp/spec.rb",
|
59
|
+
"lib/ext/blankslate.rb",
|
60
|
+
"lib/ext/em.rb",
|
61
|
+
"lib/ext/emfork.rb",
|
62
|
+
"lib/mq.rb",
|
63
|
+
"lib/mq/exchange.rb",
|
64
|
+
"lib/mq/header.rb",
|
65
|
+
"lib/mq/logger.rb",
|
66
|
+
"lib/mq/queue.rb",
|
67
|
+
"lib/mq/rpc.rb",
|
68
|
+
"old/README",
|
69
|
+
"old/Rakefile",
|
70
|
+
"old/amqp-0.8.json",
|
71
|
+
"old/amqp_spec.rb",
|
72
|
+
"old/amqpc.rb",
|
73
|
+
"old/codegen.rb",
|
74
|
+
"protocol/amqp-0.8.json",
|
75
|
+
"protocol/amqp-0.8.xml",
|
76
|
+
"protocol/codegen.rb",
|
77
|
+
"protocol/doc.txt",
|
78
|
+
"research/api.rb",
|
79
|
+
"research/primes-forked.rb",
|
80
|
+
"research/primes-processes.rb",
|
81
|
+
"research/primes-threaded.rb"
|
82
|
+
]
|
83
|
+
end
|
data/amqp.todo
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
- breaks with header values that are nil
|
2
|
+
- breaks with header values that are ruby objects (convert to strings?)
|
3
|
+
- sending utf8 data in 1.9 breaks
|
4
|
+
|
5
|
+
- generate amqp/spec.rb from original xml spec
|
6
|
+
- add peek and pop to queues
|
7
|
+
- use rabbitmq generated consumer tag from basic.consume-ok reply
|
8
|
+
|
9
|
+
- allow temporary queues with amq.queue(nil) syntax (use uuids)
|
10
|
+
- use as temp queue in rpc
|
11
|
+
- use uuids for message ids in rpc
|
12
|
+
|
13
|
+
- add ack/completed responses for messages
|
14
|
+
- deleting queues/bindings/exchanges
|
15
|
+
+ queue.unbind
|
16
|
+
- queue.remove or queue.close or queue.delete
|
17
|
+
- exchange.remove
|
18
|
+
- rpc.remove
|
19
|
+
|
20
|
+
- handle errors and exceptions
|
21
|
+
binding to a non-existent (or not yet created in clock.rb) exchange
|
22
|
+
#<AMQP::Protocol::Channel::Close:0x11d35d4
|
23
|
+
@class_id=50,
|
24
|
+
@debug=1,
|
25
|
+
@method_id=20,
|
26
|
+
@reply_code=404,
|
27
|
+
@reply_text="NOT_FOUND - no exchange 'clock' in vhost '/'">>]
|
28
|
+
|
29
|
+
- handle connection.redirect during connect (for rabbitmq in distributed mode) [or just set insist to true]
|
30
|
+
|
31
|
+
- add amq.queue('name').size{ |num| "#{num} messages in the queue" } (send declare passive, look at declare-ok response)
|
32
|
+
- clean up MQ.default on disconnect
|
data/doc/EXAMPLE_05_ACK
ADDED
data/doc/EXAMPLE_05_POP
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
|
+
require 'amqp'
|
3
|
+
|
4
|
+
module SimpleClient
|
5
|
+
def process_frame frame
|
6
|
+
case frame
|
7
|
+
when Frame::Body
|
8
|
+
EM.stop_event_loop
|
9
|
+
|
10
|
+
when Frame::Method
|
11
|
+
case method = frame.payload
|
12
|
+
when Protocol::Connection::Start
|
13
|
+
send Protocol::Connection::StartOk.new({:platform => 'Ruby/EventMachine',
|
14
|
+
:product => 'AMQP',
|
15
|
+
:information => 'http://github.com/tmm1/amqp',
|
16
|
+
:version => '0.1.0'},
|
17
|
+
'AMQPLAIN',
|
18
|
+
{:LOGIN => 'guest',
|
19
|
+
:PASSWORD => 'guest'},
|
20
|
+
'en_US')
|
21
|
+
|
22
|
+
when Protocol::Connection::Tune
|
23
|
+
send Protocol::Connection::TuneOk.new(:channel_max => 0,
|
24
|
+
:frame_max => 131072,
|
25
|
+
:heartbeat => 0)
|
26
|
+
|
27
|
+
send Protocol::Connection::Open.new(:virtual_host => '/',
|
28
|
+
:capabilities => '',
|
29
|
+
:insist => false)
|
30
|
+
|
31
|
+
when Protocol::Connection::OpenOk
|
32
|
+
send Protocol::Channel::Open.new, :channel => 1
|
33
|
+
|
34
|
+
when Protocol::Channel::OpenOk
|
35
|
+
send Protocol::Access::Request.new(:realm => '/data',
|
36
|
+
:read => true,
|
37
|
+
:write => true,
|
38
|
+
:active => true), :channel => 1
|
39
|
+
|
40
|
+
when Protocol::Access::RequestOk
|
41
|
+
@ticket = method.ticket
|
42
|
+
send Protocol::Queue::Declare.new(:ticket => @ticket,
|
43
|
+
:queue => '',
|
44
|
+
:exclusive => false,
|
45
|
+
:auto_delete => true), :channel => 1
|
46
|
+
|
47
|
+
when Protocol::Queue::DeclareOk
|
48
|
+
@queue = method.queue
|
49
|
+
send Protocol::Queue::Bind.new(:ticket => @ticket,
|
50
|
+
:queue => @queue,
|
51
|
+
:exchange => '',
|
52
|
+
:routing_key => 'test_route'), :channel => 1
|
53
|
+
|
54
|
+
when Protocol::Queue::BindOk
|
55
|
+
send Protocol::Basic::Consume.new(:ticket => @ticket,
|
56
|
+
:queue => @queue,
|
57
|
+
:no_local => false,
|
58
|
+
:no_ack => true), :channel => 1
|
59
|
+
|
60
|
+
when Protocol::Basic::ConsumeOk
|
61
|
+
data = "this is a test!"
|
62
|
+
|
63
|
+
send Protocol::Basic::Publish.new(:ticket => @ticket,
|
64
|
+
:exchange => '',
|
65
|
+
:routing_key => 'test_route'), :channel => 1
|
66
|
+
send Protocol::Header.new(Protocol::Basic, data.length, :content_type => 'application/octet-stream',
|
67
|
+
:delivery_mode => 1,
|
68
|
+
:priority => 0), :channel => 1
|
69
|
+
send Frame::Body.new(data), :channel => 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
EM.run{
|
76
|
+
AMQP.logging = true
|
77
|
+
AMQP.client = SimpleClient
|
78
|
+
AMQP.start
|
79
|
+
}
|
data/examples/mq/ack.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
# For ack to work appropriately you must shutdown AMQP gracefully,
|
5
|
+
# otherwise all items in your queue will be returned
|
6
|
+
Signal.trap('INT') { AMQP.stop{ EM.stop } }
|
7
|
+
Signal.trap('TERM'){ AMQP.stop{ EM.stop } }
|
8
|
+
|
9
|
+
AMQP.start(:host => 'localhost') do
|
10
|
+
MQ.queue('awesome').publish('Totally rad 1')
|
11
|
+
MQ.queue('awesome').publish('Totally rad 2')
|
12
|
+
MQ.queue('awesome').publish('Totally rad 3')
|
13
|
+
|
14
|
+
i = 0
|
15
|
+
|
16
|
+
# Stopping after the second item was acked will keep the 3rd item in the queue
|
17
|
+
MQ.queue('awesome').subscribe(:ack => true) do |h,m|
|
18
|
+
if (i+=1) == 3
|
19
|
+
puts 'Shutting down...'
|
20
|
+
AMQP.stop{ EM.stop }
|
21
|
+
end
|
22
|
+
|
23
|
+
if AMQP.closing?
|
24
|
+
puts "#{m} (ignored, redelivered later)"
|
25
|
+
else
|
26
|
+
puts m
|
27
|
+
h.ack
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
__END__
|
33
|
+
|
34
|
+
Totally rad 1
|
35
|
+
Totally rad 2
|
36
|
+
Shutting down...
|
37
|
+
Totally rad 3 (ignored, redelivered later)
|
38
|
+
|
39
|
+
When restarted:
|
40
|
+
|
41
|
+
Totally rad 3
|
42
|
+
Totally rad 1
|
43
|
+
Shutting down...
|
44
|
+
Totally rad 2 (ignored, redelivered later)
|
45
|
+
Totally rad 3 (ignored, redelivered later)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
AMQP.start(:host => 'localhost') do
|
5
|
+
|
6
|
+
def log *args
|
7
|
+
p args
|
8
|
+
end
|
9
|
+
|
10
|
+
# AMQP.logging = true
|
11
|
+
|
12
|
+
clock = MQ.new.fanout('clock')
|
13
|
+
EM.add_periodic_timer(1){
|
14
|
+
puts
|
15
|
+
|
16
|
+
log :publishing, time = Time.now
|
17
|
+
clock.publish(Marshal.dump(time))
|
18
|
+
}
|
19
|
+
|
20
|
+
amq = MQ.new
|
21
|
+
amq.queue('every second').bind(amq.fanout('clock')).subscribe{ |time|
|
22
|
+
log 'every second', :received, Marshal.load(time)
|
23
|
+
}
|
24
|
+
|
25
|
+
amq = MQ.new
|
26
|
+
amq.queue('every 5 seconds').bind(amq.fanout('clock')).subscribe{ |time|
|
27
|
+
time = Marshal.load(time)
|
28
|
+
log 'every 5 seconds', :received, time if time.strftime('%S').to_i%5 == 0
|
29
|
+
}
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
__END__
|
34
|
+
|
35
|
+
[:publishing, Thu Jul 17 20:14:00 -0700 2008]
|
36
|
+
["every 5 seconds", :received, Thu Jul 17 20:14:00 -0700 2008]
|
37
|
+
["every second", :received, Thu Jul 17 20:14:00 -0700 2008]
|
38
|
+
|
39
|
+
[:publishing, Thu Jul 17 20:14:01 -0700 2008]
|
40
|
+
["every second", :received, Thu Jul 17 20:14:01 -0700 2008]
|
41
|
+
|
42
|
+
[:publishing, Thu Jul 17 20:14:02 -0700 2008]
|
43
|
+
["every second", :received, Thu Jul 17 20:14:02 -0700 2008]
|
44
|
+
|
45
|
+
[:publishing, Thu Jul 17 20:14:03 -0700 2008]
|
46
|
+
["every second", :received, Thu Jul 17 20:14:03 -0700 2008]
|
47
|
+
|
48
|
+
[:publishing, Thu Jul 17 20:14:04 -0700 2008]
|
49
|
+
["every second", :received, Thu Jul 17 20:14:04 -0700 2008]
|
50
|
+
|
51
|
+
[:publishing, Thu Jul 17 20:14:05 -0700 2008]
|
52
|
+
["every 5 seconds", :received, Thu Jul 17 20:14:05 -0700 2008]
|
53
|
+
["every second", :received, Thu Jul 17 20:14:05 -0700 2008]
|
54
|
+
|
55
|
+
[:publishing, Thu Jul 17 20:14:06 -0700 2008]
|
56
|
+
["every second", :received, Thu Jul 17 20:14:06 -0700 2008]
|