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 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
+ }