tmm1-amqp 0.5.1

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