tmm1-amqp 0.5.1
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 +62 -0
- data/examples/clock.rb +56 -0
- data/examples/hashtable.rb +52 -0
- data/examples/pingpong.rb +45 -0
- data/examples/primes-forked.rb +63 -0
- data/examples/primes-processes.rb +135 -0
- data/examples/primes-simple.rb +19 -0
- data/examples/primes-threaded.rb +49 -0
- data/examples/primes.rb +99 -0
- data/examples/simple.rb +77 -0
- data/examples/stocks.rb +56 -0
- data/lib/amqp.rb +14 -0
- data/lib/amqp/buffer.rb +395 -0
- data/lib/amqp/client.rb +135 -0
- data/lib/amqp/frame.rb +124 -0
- data/lib/amqp/protocol.rb +181 -0
- data/lib/amqp/spec.rb +818 -0
- data/lib/emfork.rb +67 -0
- data/lib/mq.rb +133 -0
- data/lib/mq/exchange.rb +36 -0
- data/lib/mq/queue.rb +52 -0
- data/lib/mq/rpc.rb +51 -0
- data/protocol/amqp-0.8.json +606 -0
- data/protocol/amqp-0.8.xml +3908 -0
- data/protocol/codegen.rb +172 -0
- data/protocol/doc.txt +281 -0
- metadata +86 -0
data/README
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
Simple AMQP driver for Ruby/EventMachine.
|
2
|
+
|
3
|
+
This library was tested primarily with RabbitMQ, although it should be compatible with any
|
4
|
+
server implementing the AMQP 0-8 spec.
|
5
|
+
|
6
|
+
To use with RabbitMQ, first run the server:
|
7
|
+
|
8
|
+
hg clone http://hg.rabbitmq.com/rabbitmq-codegen
|
9
|
+
hg clone http://hg.rabbitmq.com/rabbitmq-server
|
10
|
+
cd rabbitmq-server
|
11
|
+
make run
|
12
|
+
|
13
|
+
To get started, refer to the various bundled examples:
|
14
|
+
|
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
|
20
|
+
|
21
|
+
For more details into the lower level AMQP client API, run the simple client example:
|
22
|
+
|
23
|
+
ruby examples/simple.rb
|
24
|
+
|
25
|
+
Or refer to protocol/doc.txt, which enumerates packets sent between a server and client
|
26
|
+
during a typical session, in both binary and decoded formats.
|
27
|
+
|
28
|
+
To run the test suite:
|
29
|
+
|
30
|
+
rake spec
|
31
|
+
|
32
|
+
The lib/amqp/spec.rb file is generated automatically based on the AMQP specification. To generate it:
|
33
|
+
|
34
|
+
rake codegen
|
35
|
+
|
36
|
+
This project was inspired by py-amqplib, rabbitmq, qpid and rubbyt.
|
37
|
+
Special thanks to Dmitriy Samovskiy, Ben Hood and Tony Garnock-Jones.
|
38
|
+
|
39
|
+
Other AMQP resources:
|
40
|
+
|
41
|
+
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/
|
45
|
+
|
46
|
+
John O'Hara's article on the history of AMQP:
|
47
|
+
http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=485
|
48
|
+
|
49
|
+
Barry Pederson's py-amqplib:
|
50
|
+
http://barryp.org/software/py-amqplib/
|
51
|
+
|
52
|
+
Ben Hood's article on writing an AMQP client:
|
53
|
+
http://hopper.squarespace.com/blog/2008/6/21/build-your-own-amqp-client.html
|
54
|
+
|
55
|
+
Dmitriy Samovskiy's introduction to Ruby+QPid+RabbitMQ:
|
56
|
+
http://somic-org.homelinux.org/blog/2008/06/24/ruby-amqp-rabbitmq-example/
|
57
|
+
|
58
|
+
Ben Hood's AMQP client in AS3:
|
59
|
+
http://github.com/0x6e6562/as3-amqp
|
60
|
+
|
61
|
+
RabbitMQ's protocol code generator:
|
62
|
+
http://hg.rabbitmq.com/rabbitmq-codegen/
|
data/examples/clock.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
EM.run{
|
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
|
+
}
|
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]
|
@@ -0,0 +1,52 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
EM.run{
|
5
|
+
|
6
|
+
def log *args
|
7
|
+
p args
|
8
|
+
end
|
9
|
+
|
10
|
+
# AMQP.logging = true
|
11
|
+
|
12
|
+
class HashTable < Hash
|
13
|
+
def get key
|
14
|
+
log 'HashTable', :get, key
|
15
|
+
self[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def set key, value
|
19
|
+
log 'HashTable', :set, key => value
|
20
|
+
self[key] = value
|
21
|
+
end
|
22
|
+
|
23
|
+
def keys
|
24
|
+
log 'HashTable', :keys
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
server = MQ.new.rpc('hash table node', HashTable.new)
|
30
|
+
|
31
|
+
client = MQ.new.rpc('hash table node')
|
32
|
+
client.set(:now, time = Time.now)
|
33
|
+
client.get(:now) do |res|
|
34
|
+
log 'client', :now => res, :eql? => res == time
|
35
|
+
end
|
36
|
+
|
37
|
+
client.set(:one, 1)
|
38
|
+
client.keys do |res|
|
39
|
+
log 'client', :keys => res
|
40
|
+
EM.stop_event_loop
|
41
|
+
end
|
42
|
+
|
43
|
+
}
|
44
|
+
|
45
|
+
__END__
|
46
|
+
|
47
|
+
["HashTable", :set, {:now=>Thu Jul 17 21:04:53 -0700 2008}]
|
48
|
+
["HashTable", :get, :now]
|
49
|
+
["HashTable", :set, {:one=>1}]
|
50
|
+
["HashTable", :keys]
|
51
|
+
["client", {:eql?=>true, :now=>Thu Jul 17 21:04:53 -0700 2008}]
|
52
|
+
["client", {:keys=>[:one, :now]}]
|
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
EM.run{
|
5
|
+
|
6
|
+
def log *args
|
7
|
+
p [ Time.now, *args ]
|
8
|
+
end
|
9
|
+
|
10
|
+
# AMQP.logging = true
|
11
|
+
|
12
|
+
amq = MQ.new
|
13
|
+
EM.add_periodic_timer(1){
|
14
|
+
puts
|
15
|
+
|
16
|
+
log :sending, 'ping'
|
17
|
+
amq.queue('one').publish('ping')
|
18
|
+
}
|
19
|
+
|
20
|
+
amq = MQ.new
|
21
|
+
amq.queue('one').subscribe{ |msg|
|
22
|
+
log 'one', :received, msg, :sending, 'pong'
|
23
|
+
amq.queue('two').publish('pong')
|
24
|
+
}
|
25
|
+
|
26
|
+
amq = MQ.new
|
27
|
+
amq.queue('two').subscribe{ |msg|
|
28
|
+
log 'two', :received, msg
|
29
|
+
}
|
30
|
+
|
31
|
+
}
|
32
|
+
|
33
|
+
__END__
|
34
|
+
|
35
|
+
[Sun Jul 20 03:52:24 -0700 2008, :sending, "ping"]
|
36
|
+
[Sun Jul 20 03:52:24 -0700 2008, "one", :received, "ping", :sending, "pong"]
|
37
|
+
[Sun Jul 20 03:52:24 -0700 2008, "two", :received, "pong"]
|
38
|
+
|
39
|
+
[Sun Jul 20 03:52:25 -0700 2008, :sending, "ping"]
|
40
|
+
[Sun Jul 20 03:52:25 -0700 2008, "one", :received, "ping", :sending, "pong"]
|
41
|
+
[Sun Jul 20 03:52:25 -0700 2008, "two", :received, "pong"]
|
42
|
+
|
43
|
+
[Sun Jul 20 03:52:26 -0700 2008, :sending, "ping"]
|
44
|
+
[Sun Jul 20 03:52:26 -0700 2008, "one", :received, "ping", :sending, "pong"]
|
45
|
+
[Sun Jul 20 03:52:26 -0700 2008, "two", :received, "pong"]
|
@@ -0,0 +1,63 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
MAX = 5000
|
5
|
+
|
6
|
+
def EM.fork &blk
|
7
|
+
raise if reactor_running?
|
8
|
+
|
9
|
+
unless @forks
|
10
|
+
at_exit{
|
11
|
+
@forks.each{ |pid| Process.kill('KILL', pid) }
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
(@forks ||= []) << Kernel.fork do
|
16
|
+
EM.run(&blk)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def log *args
|
21
|
+
p args
|
22
|
+
end
|
23
|
+
|
24
|
+
# MQ.logging = true
|
25
|
+
|
26
|
+
# worker
|
27
|
+
|
28
|
+
workers = ARGV[0] ? (Integer(ARGV[0]) rescue 2) : 2
|
29
|
+
|
30
|
+
workers.times do
|
31
|
+
EM.fork{
|
32
|
+
log "prime checker", Process.pid, :started
|
33
|
+
|
34
|
+
class Fixnum
|
35
|
+
def prime?
|
36
|
+
('1' * self) !~ /^1?$|^(11+?)\1+$/
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
MQ.queue('prime checker').subscribe{ |info, num|
|
41
|
+
log "prime checker #{Process.pid}", :prime?, num
|
42
|
+
if Integer(num).prime?
|
43
|
+
MQ.queue(info.reply_to).publish(num, :reply_to => Process.pid)
|
44
|
+
end
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
# controller
|
50
|
+
|
51
|
+
EM.run{
|
52
|
+
MQ.queue('prime collector').subscribe{ |info, prime|
|
53
|
+
log 'prime collector', :received, prime, :from, info.reply_to
|
54
|
+
(@primes ||= []) << Integer(prime)
|
55
|
+
EM.stop_event_loop if prime == '499'
|
56
|
+
}
|
57
|
+
|
58
|
+
MAX.times do |i|
|
59
|
+
EM.next_tick do
|
60
|
+
MQ.queue('prime checker').publish((i+1).to_s, :reply_to => 'prime collector')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
}
|
@@ -0,0 +1,135 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
MAX = 500
|
5
|
+
|
6
|
+
EM.run{
|
7
|
+
|
8
|
+
def log *args
|
9
|
+
p args
|
10
|
+
end
|
11
|
+
|
12
|
+
# MQ.logging = true
|
13
|
+
|
14
|
+
if ARGV[0] == 'worker'
|
15
|
+
|
16
|
+
log "prime checker #{Process.pid}", :started
|
17
|
+
|
18
|
+
class Fixnum
|
19
|
+
def prime?
|
20
|
+
('1' * self) !~ /^1?$|^(11+?)\1+$/
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
MQ.queue('prime checker').subscribe{ |info, num|
|
25
|
+
log "prime checker #{Process.pid}", :prime?, num
|
26
|
+
if Integer(num).prime?
|
27
|
+
MQ.queue(info.reply_to).publish(num, :reply_to => Process.pid)
|
28
|
+
EM.stop_event_loop if num == (MAX-1).to_s
|
29
|
+
end
|
30
|
+
}
|
31
|
+
|
32
|
+
elsif ARGV[0] == 'controller'
|
33
|
+
|
34
|
+
MQ.queue('prime collector').subscribe{ |info, prime|
|
35
|
+
log 'prime collector', :received, prime, :from, info.reply_to
|
36
|
+
(@primes ||= []) << Integer(prime)
|
37
|
+
}
|
38
|
+
|
39
|
+
MAX.times do |i|
|
40
|
+
EM.next_tick do
|
41
|
+
MQ.queue('prime checker').publish((i+1).to_s, :reply_to => 'prime collector')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
else # run n workers and 1 controller as an example
|
46
|
+
|
47
|
+
workers = ARGV[0] ? (Integer(ARGV[0]) rescue 2) : 2
|
48
|
+
|
49
|
+
([ :worker ] * workers + [ :controller ]).each do |type|
|
50
|
+
log :spawning, "`ruby #{$0} #{type}`"
|
51
|
+
|
52
|
+
EM.popen("ruby #{$0} #{type}") do |c|
|
53
|
+
def c.receive_data data
|
54
|
+
puts data
|
55
|
+
end
|
56
|
+
|
57
|
+
def c.unbind
|
58
|
+
EM.stop_event_loop
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
}
|
65
|
+
|
66
|
+
__END__
|
67
|
+
|
68
|
+
["prime checker", :started, {:pid=>1958}]
|
69
|
+
["prime checker", :started, {:pid=>1957}]
|
70
|
+
["prime checker", :started, {:pid=>1956}]
|
71
|
+
["prime checker", :prime?, "1", {:pid=>1958}]
|
72
|
+
["prime checker", :prime?, "2", {:pid=>1957}]
|
73
|
+
["prime collector", :received, "2", {:from_pid=>"1957"}]
|
74
|
+
["prime checker", :prime?, "3", {:pid=>1956}]
|
75
|
+
["prime collector", :received, "3", {:from_pid=>"1956"}]
|
76
|
+
["prime checker", :prime?, "4", {:pid=>1958}]
|
77
|
+
["prime checker", :prime?, "5", {:pid=>1957}]
|
78
|
+
["prime collector", :received, "5", {:from_pid=>"1957"}]
|
79
|
+
["prime checker", :prime?, "6", {:pid=>1956}]
|
80
|
+
["prime checker", :prime?, "7", {:pid=>1958}]
|
81
|
+
["prime collector", :received, "7", {:from_pid=>"1958"}]
|
82
|
+
["prime checker", :prime?, "8", {:pid=>1957}]
|
83
|
+
["prime checker", :prime?, "9", {:pid=>1956}]
|
84
|
+
["prime checker", :prime?, "10", {:pid=>1958}]
|
85
|
+
["prime checker", :prime?, "11", {:pid=>1957}]
|
86
|
+
["prime collector", :received, "11", {:from_pid=>"1957"}]
|
87
|
+
["prime checker", :prime?, "12", {:pid=>1956}]
|
88
|
+
["prime checker", :prime?, "13", {:pid=>1958}]
|
89
|
+
["prime collector", :received, "13", {:from_pid=>"1958"}]
|
90
|
+
["prime checker", :prime?, "14", {:pid=>1957}]
|
91
|
+
["prime checker", :prime?, "15", {:pid=>1956}]
|
92
|
+
["prime checker", :prime?, "16", {:pid=>1958}]
|
93
|
+
["prime checker", :prime?, "17", {:pid=>1957}]
|
94
|
+
["prime collector", :received, "17", {:from_pid=>"1957"}]
|
95
|
+
["prime checker", :prime?, "18", {:pid=>1956}]
|
96
|
+
["prime checker", :prime?, "19", {:pid=>1958}]
|
97
|
+
["prime collector", :received, "19", {:from_pid=>"1958"}]
|
98
|
+
["prime checker", :prime?, "20", {:pid=>1957}]
|
99
|
+
["prime checker", :prime?, "21", {:pid=>1956}]
|
100
|
+
["prime checker", :prime?, "22", {:pid=>1958}]
|
101
|
+
["prime checker", :prime?, "23", {:pid=>1957}]
|
102
|
+
["prime collector", :received, "23", {:from_pid=>"1957"}]
|
103
|
+
["prime checker", :prime?, "24", {:pid=>1956}]
|
104
|
+
["prime checker", :prime?, "25", {:pid=>1958}]
|
105
|
+
["prime checker", :prime?, "26", {:pid=>1957}]
|
106
|
+
["prime checker", :prime?, "27", {:pid=>1956}]
|
107
|
+
["prime checker", :prime?, "28", {:pid=>1958}]
|
108
|
+
["prime checker", :prime?, "29", {:pid=>1957}]
|
109
|
+
["prime collector", :received, "29", {:from_pid=>"1957"}]
|
110
|
+
["prime checker", :prime?, "30", {:pid=>1956}]
|
111
|
+
["prime checker", :prime?, "31", {:pid=>1958}]
|
112
|
+
["prime collector", :received, "31", {:from_pid=>"1958"}]
|
113
|
+
["prime checker", :prime?, "32", {:pid=>1957}]
|
114
|
+
["prime checker", :prime?, "33", {:pid=>1956}]
|
115
|
+
["prime checker", :prime?, "34", {:pid=>1958}]
|
116
|
+
["prime checker", :prime?, "35", {:pid=>1957}]
|
117
|
+
["prime checker", :prime?, "36", {:pid=>1956}]
|
118
|
+
["prime checker", :prime?, "37", {:pid=>1958}]
|
119
|
+
["prime collector", :received, "37", {:from_pid=>"1958"}]
|
120
|
+
["prime checker", :prime?, "38", {:pid=>1957}]
|
121
|
+
["prime checker", :prime?, "39", {:pid=>1956}]
|
122
|
+
["prime checker", :prime?, "40", {:pid=>1958}]
|
123
|
+
["prime checker", :prime?, "41", {:pid=>1957}]
|
124
|
+
["prime collector", :received, "41", {:from_pid=>"1957"}]
|
125
|
+
["prime checker", :prime?, "42", {:pid=>1956}]
|
126
|
+
["prime checker", :prime?, "43", {:pid=>1958}]
|
127
|
+
["prime collector", :received, "43", {:from_pid=>"1958"}]
|
128
|
+
["prime checker", :prime?, "44", {:pid=>1957}]
|
129
|
+
["prime checker", :prime?, "45", {:pid=>1956}]
|
130
|
+
["prime checker", :prime?, "46", {:pid=>1958}]
|
131
|
+
["prime checker", :prime?, "47", {:pid=>1957}]
|
132
|
+
["prime collector", :received, "47", {:from_pid=>"1957"}]
|
133
|
+
["prime checker", :prime?, "48", {:pid=>1956}]
|
134
|
+
["prime checker", :prime?, "49", {:pid=>1958}]
|
135
|
+
["prime checker", :prime?, "50", {:pid=>1957}]
|
@@ -0,0 +1,19 @@
|
|
1
|
+
MAX = 1000
|
2
|
+
|
3
|
+
class Fixnum
|
4
|
+
def prime?
|
5
|
+
('1' * self) !~ /^1?$|^(11+?)\1+$/
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class PrimeChecker
|
10
|
+
def is_prime? number
|
11
|
+
number.prime?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
prime_checker = PrimeChecker.new
|
16
|
+
|
17
|
+
(10_000...(10_000+MAX)).each do |n|
|
18
|
+
prime_checker.is_prime? n
|
19
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'mq'
|
3
|
+
|
4
|
+
MAX = 500
|
5
|
+
|
6
|
+
def log *args
|
7
|
+
p args
|
8
|
+
end
|
9
|
+
|
10
|
+
# MQ.logging = true
|
11
|
+
|
12
|
+
EM.run{
|
13
|
+
|
14
|
+
# worker
|
15
|
+
|
16
|
+
log "prime checker", Process.pid, :started
|
17
|
+
|
18
|
+
class Fixnum
|
19
|
+
def prime?
|
20
|
+
('1' * self) !~ /^1?$|^(11+?)\1+$/
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
MQ.queue('prime checker').subscribe{ |info, num|
|
25
|
+
EM.defer(proc{
|
26
|
+
|
27
|
+
log "prime checker #{Process.pid}-#{Thread.current.object_id}", :prime?, num
|
28
|
+
if Integer(num).prime?
|
29
|
+
MQ.queue(info.reply_to).publish(num, :reply_to => "#{Process.pid}-#{Thread.current.object_id}")
|
30
|
+
EM.stop_event_loop if num == '499'
|
31
|
+
end
|
32
|
+
|
33
|
+
})
|
34
|
+
}
|
35
|
+
|
36
|
+
# controller
|
37
|
+
|
38
|
+
MQ.queue('prime collector').subscribe{ |info, prime|
|
39
|
+
log 'prime collector', :received, prime, :from, info.reply_to
|
40
|
+
(@primes ||= []) << Integer(prime)
|
41
|
+
}
|
42
|
+
|
43
|
+
MAX.times do |i|
|
44
|
+
EM.next_tick do
|
45
|
+
MQ.queue('prime checker').publish((i+1).to_s, :reply_to => 'prime collector')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
}
|