amqp 0.7.0.pre → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/CHANGELOG +8 -2
- data/CONTRIBUTORS +22 -0
- data/Gemfile +3 -3
- data/README.md +20 -11
- data/Rakefile +30 -6
- data/amqp.gemspec +1 -1
- data/bin/cleanify.rb +50 -0
- data/examples/amqp/simple.rb +6 -4
- data/examples/mq/ack.rb +8 -6
- data/examples/mq/automatic_binding_for_default_direct_exchange.rb +65 -0
- data/examples/mq/callbacks.rb +9 -1
- data/examples/mq/clock.rb +17 -17
- data/examples/mq/hashtable.rb +19 -10
- data/examples/mq/internal.rb +13 -11
- data/examples/mq/logger.rb +38 -36
- data/examples/mq/multiclock.rb +16 -7
- data/examples/mq/pingpong.rb +16 -7
- data/examples/mq/pop.rb +8 -6
- data/examples/mq/primes-simple.rb +2 -0
- data/examples/mq/primes.rb +7 -5
- data/examples/mq/stocks.rb +14 -5
- data/lib/amqp.rb +12 -8
- data/lib/amqp/buffer.rb +35 -158
- data/lib/amqp/client.rb +34 -22
- data/lib/amqp/frame.rb +8 -64
- data/lib/amqp/protocol.rb +21 -70
- data/lib/amqp/server.rb +11 -9
- data/lib/amqp/spec.rb +8 -6
- data/lib/amqp/version.rb +2 -0
- data/lib/ext/blankslate.rb +3 -1
- data/lib/ext/em.rb +2 -0
- data/lib/ext/emfork.rb +13 -11
- data/lib/mq.rb +253 -156
- data/lib/mq/collection.rb +6 -88
- data/lib/mq/exchange.rb +70 -13
- data/lib/mq/header.rb +12 -6
- data/lib/mq/logger.rb +9 -7
- data/lib/mq/queue.rb +42 -30
- data/lib/mq/rpc.rb +6 -4
- data/protocol/codegen.rb +20 -18
- data/research/api.rb +10 -46
- data/research/primes-forked.rb +9 -7
- data/research/primes-processes.rb +74 -72
- data/research/primes-threaded.rb +9 -7
- data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +61 -0
- data/spec/mq_helper.rb +70 -0
- data/spec/spec_helper.rb +84 -29
- data/spec/unit/amqp/buffer_spec.rb +178 -0
- data/spec/unit/amqp/client_spec.rb +472 -0
- data/spec/unit/amqp/frame_spec.rb +60 -0
- data/spec/unit/amqp/misc_spec.rb +123 -0
- data/spec/unit/amqp/protocol_spec.rb +53 -0
- data/spec/unit/mq/channel_close_spec.rb +15 -0
- data/spec/unit/mq/collection_spec.rb +129 -0
- data/spec/unit/mq/exchange_declaration_spec.rb +524 -0
- data/spec/unit/mq/misc_spec.rb +228 -0
- data/spec/unit/mq/mq_basic_spec.rb +39 -0
- data/spec/unit/mq/queue_declaration_spec.rb +97 -0
- data/spec/unit/mq/queue_spec.rb +71 -0
- metadata +33 -21
- data/Gemfile.lock +0 -16
- data/old/README +0 -30
- data/old/Rakefile +0 -12
- data/old/amqp-0.8.json +0 -606
- data/old/amqp_spec.rb +0 -796
- data/old/amqpc.rb +0 -695
- data/old/codegen.rb +0 -148
- data/spec/channel_close_spec.rb +0 -13
- data/spec/sync_async_spec.rb +0 -52
data/.gitignore
CHANGED
data/.rspec
ADDED
data/CHANGELOG
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
= Version 0.7
|
2
2
|
* [BUG] Sync API for queues and exchanges, support for server-generated queues & exchange names (via semi-lazy collection).
|
3
3
|
* [BUG] Sync API for MQ#close (Channel.Close) [issue #34].
|
4
|
-
* [FEATURE]
|
5
|
-
* [DEVELOP] some em-spec-based specs, bin/irb, Gemfile.
|
4
|
+
* [FEATURE] AMQP URL from majek's fork, with some fixes. Example: AMQP.start("amqps://")
|
5
|
+
* [DEVELOP] Added some em-spec-based specs, bin/irb, Gemfile.
|
6
|
+
* [FEATURE] Added MQ::Exchange.default for the default exchange.
|
7
|
+
* [FEATURE] Raise an exception if we're trying to use Basic.Reject with RabbitMQ.
|
8
|
+
* [FEATURE] Fail if an entity is re-declared with different options.
|
9
|
+
* [BUG] Don't reconnect if the credentials are wrong.
|
10
|
+
* [BUG] Fixed an exception which occurred when Queue#bind was called synchronously with a callback.
|
11
|
+
* [DEVELOPMENT] Added a lot of specs (Bacon replaced by rSpec 2).
|
data/CONTRIBUTORS
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Aman Gupta: 232
|
2
|
+
Jakub Šťastný aka Botanicus: 57
|
3
|
+
arvicco: 26
|
4
|
+
Michael S. Klishin: 17
|
5
|
+
Chuck Remes: 7
|
6
|
+
Marek Majkowski: 4
|
7
|
+
Chris Van Pelt: 3
|
8
|
+
Jake Douglas: 3
|
9
|
+
Doug Barth: 2
|
10
|
+
coderrr: 2
|
11
|
+
binary42: 1
|
12
|
+
Daniel Neighman: 1
|
13
|
+
Brendan Ribera: 1
|
14
|
+
dan: 1
|
15
|
+
Dane Jensen: 1
|
16
|
+
Tony Garnock-Jones: 1
|
17
|
+
Phil Smith: 1
|
18
|
+
Kasper Bjørn Nielsen: 1
|
19
|
+
Simon Horne: 1
|
20
|
+
Cliff Moon: 1
|
21
|
+
Coda Hale: 1
|
22
|
+
John Richmond: 1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -45,8 +45,8 @@ How to use AMQP gem with Ruby on Rails, Merb, Sinatra and other web frameworks
|
|
45
45
|
==============================================================================
|
46
46
|
|
47
47
|
To use AMQP gem from web applications, you would need to have EventMachine reactor running.
|
48
|
-
If you use [Thin](http://code.macournoyer.com/thin/), you are set: Thin uses EventMachine under
|
49
|
-
the
|
48
|
+
If you use [Thin](http://code.macournoyer.com/thin/), you are all set: Thin uses EventMachine under
|
49
|
+
the hood.
|
50
50
|
|
51
51
|
With other web servers, you need to start EventMachine reactor in it's own thread like this:
|
52
52
|
|
@@ -61,31 +61,41 @@ In a Ruby on Rails app, probably the best place for this code is initializer
|
|
61
61
|
Sinatra and pure Rack applications, place it next to other configuration
|
62
62
|
code.
|
63
63
|
|
64
|
+
If you want to integrate AMQP with Thin or another EventMachine-based software which already runs an event loop, you might want to use following code:
|
65
|
+
|
66
|
+
EM.next_tick { AMQP.connect(...) }
|
67
|
+
|
68
|
+
So in case the reactor isn't running yet (which seems to be the case with Ruby on Rails 3.x and Thin combination), it won't fail, but wait when the reactor is started (see [issue #21](https://github.com/tmm1/amqp/issues/21)).
|
69
|
+
|
64
70
|
Same separate thread technique can be used to make EventMachine play nicely with other
|
65
71
|
libraries that would block current thread (like [File::Tail](http://rubygems.org/gems/file-tail)).
|
66
72
|
|
67
|
-
|
73
|
+
Links
|
68
74
|
==============================
|
69
75
|
|
76
|
+
* Jabber chat [amqp-dev@conf.netlab.cz](xmpp://amqp-dev@conf.netlab.cz)
|
70
77
|
* [AMQP gem mailing list](http://groups.google.com/group/ruby-amqp)
|
71
|
-
* [AMQP gem at GitHub](http://github.com/
|
78
|
+
* [AMQP gem at GitHub](http://github.com/amqp-dev/amqp)
|
72
79
|
* [AMQP gem at Gemcutter](http://rubygems.org/gems/amqp)
|
73
80
|
|
74
|
-
|
81
|
+
Contributions
|
75
82
|
============================
|
76
83
|
|
77
|
-
|
84
|
+
All the dependencies are specified in <code>Gemfile</code>, so if you have [Bundler](http://gembundler.com), you can just run <code>bundle install</code>.
|
78
85
|
|
79
|
-
|
80
|
-
|
81
|
-
The lib/amqp/spec.rb file is generated automatically based on the [AMQP specification](http://www.amqp.org/confluence/display/AMQP/AMQP+Specification). To generate it:
|
86
|
+
The <code>lib/amqp/spec.rb</code> file is generated automatically based on the [AMQP specification](http://www.amqp.org/confluence/display/AMQP/AMQP+Specification). To generate it:
|
82
87
|
|
83
88
|
rake codegen
|
84
89
|
|
90
|
+
For running specs, use <code>rake spec</code>.
|
91
|
+
|
85
92
|
Credits and more information
|
86
93
|
============================
|
87
94
|
|
88
|
-
|
95
|
+
* The Original Code is tmm1/amqp.
|
96
|
+
* The Initial Developer of the Original Code is Aman Gupta.
|
97
|
+
* Copyright (c) 2008 - 2010 [Aman Gupta](http://github.com/tmm1) (tmm1).
|
98
|
+
* Contributions from Jakub Stastny are Copyright (c) 2011 VMware, Inc.
|
89
99
|
|
90
100
|
Current maintainer: [Jakub Stastny](http://github.com/botanicus) aka [botanicus](http://twitter.com/botanicus).
|
91
101
|
|
@@ -96,7 +106,6 @@ AMQP brokers
|
|
96
106
|
------------
|
97
107
|
|
98
108
|
* [RabbitMQ](http://rabbitmq.com) (Rabbit Technologies, Erlang/OTP, MPL)
|
99
|
-
* [ZeroMQ](http://www.zeromq.org) (iMatix/FastMQ/Intel, C++, GPL3)
|
100
109
|
* [OpenAMQ](http://openamq.org) (iMatix, C, GPL2)
|
101
110
|
* [ActiveMQ](http://activemq.apache.org) (Apache Foundation, Java, Apache2)
|
102
111
|
|
data/Rakefile
CHANGED
@@ -1,14 +1,20 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
|
3
|
+
desc "Run spec suite (uses Rspec2)"
|
4
|
+
RSpec::Core::RakeTask.new(:spec) { |t|}
|
5
|
+
|
6
|
+
desc "Run specs with RCov"
|
7
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
8
|
+
t.rcov = true
|
9
|
+
t.rcov_opts = ['--exclude', 'spec']
|
10
|
+
end
|
11
|
+
|
1
12
|
desc "Generate AMQP specification classes"
|
2
13
|
task :codegen do
|
3
14
|
sh 'ruby protocol/codegen.rb > lib/amqp/spec.rb'
|
4
15
|
sh 'ruby lib/amqp/spec.rb'
|
5
16
|
end
|
6
17
|
|
7
|
-
desc "Run spec suite (uses bacon gem)"
|
8
|
-
task :spec do
|
9
|
-
sh 'bacon lib/amqp.rb'
|
10
|
-
end
|
11
|
-
|
12
18
|
desc "Build the gem"
|
13
19
|
task :gem do
|
14
20
|
sh 'gem build *.gemspec'
|
@@ -17,4 +23,22 @@ end
|
|
17
23
|
desc "Synonym for gem"
|
18
24
|
task :pkg => :gem
|
19
25
|
desc "Synonym for gem"
|
20
|
-
task :package => :gem
|
26
|
+
task :package => :gem
|
27
|
+
|
28
|
+
|
29
|
+
desc "Regenerate contributors file."
|
30
|
+
task :contributors do
|
31
|
+
authors = %x{git log | grep ^Author:}.split("\n")
|
32
|
+
results = authors.reduce(Hash.new) do |results, line|
|
33
|
+
name = line.sub(/^Author: (.+) <.+>$/, '\1')
|
34
|
+
results[name] ||= 0
|
35
|
+
results[name] += 1
|
36
|
+
results
|
37
|
+
end
|
38
|
+
results = results.sort_by { |_, count| count }.reverse
|
39
|
+
File.open("CONTRIBUTORS", "w") do |file|
|
40
|
+
results.each do |name, count|
|
41
|
+
file.puts "#{name}: #{count}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/amqp.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.name = "amqp"
|
9
9
|
s.version = AMQP::VERSION
|
10
10
|
s.authors = ["Aman Gupta", "Jakub Stastny aka botanicus"]
|
11
|
-
s.homepage = "http://github.com/
|
11
|
+
s.homepage = "http://github.com/ruby-amqp/amqp"
|
12
12
|
s.summary = "AMQP client implementation in Ruby/EventMachine."
|
13
13
|
s.description = "An implementation of the AMQP protocol in Ruby/EventMachine for writing clients to the RabbitMQ message broker."
|
14
14
|
s.cert_chain = nil
|
data/bin/cleanify.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby -i
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Usage:
|
5
|
+
# find . | egrep '\.rb$' | egrep -v cleanify.rb | xargs ./bin/cleanify.rb
|
6
|
+
|
7
|
+
# \n at the end of the file
|
8
|
+
# def foo a, b, &block
|
9
|
+
# no trailing whitespace
|
10
|
+
# encoding declaration
|
11
|
+
|
12
|
+
ENCODING = "utf-8"
|
13
|
+
|
14
|
+
while line = ARGF.gets
|
15
|
+
# whitespace
|
16
|
+
# line.chomp!
|
17
|
+
line.gsub!(/\t/, " ")
|
18
|
+
line.rstrip!
|
19
|
+
|
20
|
+
# encoding
|
21
|
+
if line.length == (ARGF.pos - 1) && ! line.match(/^#.*coding/)
|
22
|
+
puts "# encoding: #{ENCODING}\n\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
# def
|
26
|
+
regexp = /^(\s*def \w[\w\d]*)\s+(.+)$/
|
27
|
+
if line.match(regexp)
|
28
|
+
line.gsub!(regexp, '\1(\2)')
|
29
|
+
end
|
30
|
+
|
31
|
+
# foo{} => foo {}
|
32
|
+
line.gsub!(/([^%][^#( ])(\{)/, '\1 \2')
|
33
|
+
|
34
|
+
# a=foo => a = foo
|
35
|
+
line.gsub!(/([^ ])(\+=)/, '\1 \2')
|
36
|
+
line.gsub!(/(\+=)([^ ])/, '\1 \2')
|
37
|
+
line.gsub!(/([^ :])(<<)/, '\1 \2')
|
38
|
+
line.gsub!(/(<<)([^ ])/, '\1 \2')
|
39
|
+
|
40
|
+
# foo=>bar
|
41
|
+
line.gsub!(/([^\s])=>/, '\1 =>')
|
42
|
+
line.gsub!(/=>([^\s])/, '=> \1')
|
43
|
+
|
44
|
+
line.gsub!(/\{\|/, '{ |')
|
45
|
+
|
46
|
+
line.gsub!(/,\s*/, ', ')
|
47
|
+
line.rstrip!
|
48
|
+
|
49
|
+
puts line
|
50
|
+
end
|
data/examples/amqp/simple.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
4
|
require 'amqp'
|
3
5
|
|
4
6
|
module SimpleClient
|
5
|
-
def process_frame
|
7
|
+
def process_frame(frame)
|
6
8
|
case frame
|
7
9
|
when Frame::Body
|
8
10
|
EM.stop_event_loop
|
@@ -12,7 +14,7 @@ module SimpleClient
|
|
12
14
|
when Protocol::Connection::Start
|
13
15
|
send Protocol::Connection::StartOk.new({:platform => 'Ruby/EventMachine',
|
14
16
|
:product => 'AMQP',
|
15
|
-
:information => 'http://github.com/
|
17
|
+
:information => 'http://github.com/ruby-amqp/amqp',
|
16
18
|
:version => '0.1.0'},
|
17
19
|
'AMQPLAIN',
|
18
20
|
{:LOGIN => 'guest',
|
@@ -72,8 +74,8 @@ module SimpleClient
|
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
|
-
EM.run{
|
77
|
+
EM.run {
|
76
78
|
AMQP.logging = true
|
77
79
|
AMQP.client = SimpleClient
|
78
80
|
AMQP.start
|
79
|
-
}
|
81
|
+
}
|
data/examples/mq/ack.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
4
|
require 'mq'
|
3
5
|
|
4
6
|
# For ack to work appropriately you must shutdown AMQP gracefully,
|
5
7
|
# 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
|
+
Signal.trap('INT') { AMQP.stop { EM.stop } }
|
9
|
+
Signal.trap('TERM') { AMQP.stop { EM.stop } }
|
8
10
|
|
9
11
|
AMQP.start(:host => 'localhost') do
|
10
12
|
MQ.queue('awesome').publish('Totally rad 1')
|
@@ -14,10 +16,10 @@ AMQP.start(:host => 'localhost') do
|
|
14
16
|
i = 0
|
15
17
|
|
16
18
|
# 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
|
+
MQ.queue('awesome').subscribe(:ack => true) do |h, m|
|
20
|
+
if (i += 1) == 3
|
19
21
|
puts 'Shutting down...'
|
20
|
-
AMQP.stop{ EM.stop }
|
22
|
+
AMQP.stop { EM.stop }
|
21
23
|
end
|
22
24
|
|
23
25
|
if AMQP.closing?
|
@@ -42,4 +44,4 @@ Totally rad 3
|
|
42
44
|
Totally rad 1
|
43
45
|
Shutting down...
|
44
46
|
Totally rad 2 (ignored, redelivered later)
|
45
|
-
Totally rad 3 (ignored, redelivered later)
|
47
|
+
Totally rad 3 (ignored, redelivered later)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
4
|
+
|
5
|
+
require 'mq'
|
6
|
+
|
7
|
+
if RUBY_VERSION == "1.8.7"
|
8
|
+
module ArrayExtensions
|
9
|
+
def sample
|
10
|
+
self.choice
|
11
|
+
end # sample
|
12
|
+
end
|
13
|
+
|
14
|
+
class Array
|
15
|
+
include ArrayExtensions
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
EM.run do
|
22
|
+
connection = AMQP.connect
|
23
|
+
mq = MQ.new(connection)
|
24
|
+
|
25
|
+
show_stopper = Proc.new do
|
26
|
+
$stdout.puts "Stopping..."
|
27
|
+
# now change this to just EM.stop and it
|
28
|
+
# unbinds instantly
|
29
|
+
connection.close {
|
30
|
+
EM.stop { exit }
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
Signal.trap "INT", &show_stopper
|
35
|
+
|
36
|
+
$stdout.puts "Bound! Running #{AMQP::VERSION} version of the gem."
|
37
|
+
|
38
|
+
queue1 = mq.queue("queue1")
|
39
|
+
queue2 = mq.queue("queue2")
|
40
|
+
queue3 = mq.queue("queue3")
|
41
|
+
|
42
|
+
queues = [queue1, queue2, queue3]
|
43
|
+
|
44
|
+
# Rely on default direct exchange binding, see section 2.1.2.4 Automatic Mode in AMQP 0.9.1 spec.
|
45
|
+
exchange = MQ::Exchange.default
|
46
|
+
|
47
|
+
queue1.subscribe do |payload|
|
48
|
+
puts "Got #{payload} for #{queue1.name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
queue2.subscribe do |payload|
|
52
|
+
puts "New message to queue #{queue2.name}"
|
53
|
+
end
|
54
|
+
|
55
|
+
queue3.subscribe do |payload|
|
56
|
+
puts "There is a message for #{queue3.name}"
|
57
|
+
end
|
58
|
+
|
59
|
+
EM.add_periodic_timer(1) do
|
60
|
+
q = queues.sample
|
61
|
+
|
62
|
+
$stdout.puts "Publishing to default exchange with routing key = #{q.name}..."
|
63
|
+
exchange.publish "Some payload", :routing_key => q.name
|
64
|
+
end
|
65
|
+
end
|
data/examples/mq/callbacks.rb
CHANGED
@@ -3,7 +3,15 @@
|
|
3
3
|
$:.unshift File.expand_path("../../../lib", __FILE__)
|
4
4
|
require "mq"
|
5
5
|
|
6
|
-
AMQP.start(:host => "localhost") do
|
6
|
+
AMQP.start(:host => "localhost") do |connection|
|
7
|
+
|
8
|
+
# Send Connection.Close on Ctrl+C
|
9
|
+
trap(:INT) do
|
10
|
+
unless connection.closing?
|
11
|
+
connection.close { exit! }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
@counter = 0
|
8
16
|
amq = MQ.new
|
9
17
|
|
data/examples/mq/clock.rb
CHANGED
@@ -1,42 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
2
4
|
require 'mq'
|
3
5
|
|
4
|
-
AMQP.start(:host => 'localhost'
|
6
|
+
AMQP.start(:host => 'localhost') do |connection|
|
7
|
+
|
8
|
+
# Send Connection.Close on Ctrl+C
|
9
|
+
trap(:INT) do
|
10
|
+
unless connection.closing?
|
11
|
+
connection.close { exit! }
|
12
|
+
end
|
13
|
+
end
|
5
14
|
|
6
|
-
def log
|
15
|
+
def log(*args)
|
7
16
|
p args
|
8
17
|
end
|
9
18
|
|
10
19
|
# AMQP.logging = true
|
11
20
|
|
12
21
|
clock = MQ.new.fanout('clock')
|
13
|
-
|
14
|
-
|
15
|
-
EM.add_periodic_timer(1){
|
22
|
+
EM.add_periodic_timer(1) {
|
16
23
|
puts
|
17
24
|
|
18
25
|
log :publishing, time = Time.now
|
19
26
|
clock.publish(Marshal.dump(time))
|
20
27
|
}
|
21
28
|
|
22
|
-
EM.add_periodic_timer(1){
|
23
|
-
puts
|
24
|
-
|
25
|
-
log 2, :publishing, time = Time.now
|
26
|
-
clock.publish(Marshal.dump(time))
|
27
|
-
}
|
28
|
-
|
29
29
|
amq = MQ.new
|
30
|
-
|
31
|
-
q.bind(amq.fanout('clock')).subscribe{ |time|
|
30
|
+
amq.queue('every second').bind(amq.fanout('clock')).subscribe { |time|
|
32
31
|
log 'every second', :received, Marshal.load(time)
|
33
32
|
}
|
34
33
|
|
35
|
-
amq
|
36
|
-
|
34
|
+
amq = MQ.new
|
35
|
+
amq.queue('every 5 seconds').bind(amq.fanout('clock')).subscribe { |time|
|
36
|
+
time = Marshal.load(time)
|
37
|
+
log 'every 5 seconds', :received, time if time.strftime('%S').to_i % 5 == 0
|
37
38
|
}
|
38
39
|
|
39
|
-
|
40
40
|
end
|
41
41
|
|
42
42
|
__END__
|