pipeline_toolkit 1.0.4 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.markdown +20 -0
- data/README.markdown +98 -0
- data/bin/msg_generator +13 -0
- data/bin/msg_probe +13 -0
- data/bin/msg_push +13 -0
- data/bin/msg_sink +14 -0
- data/bin/msg_subscribe +13 -0
- data/lib/pipeline_toolkit.rb +17 -0
- data/lib/pipeline_toolkit/amqp/abstract.rb +95 -0
- data/lib/pipeline_toolkit/amqp/reader.rb +64 -0
- data/lib/pipeline_toolkit/amqp/writer.rb +54 -0
- data/lib/pipeline_toolkit/commands/msg_generator/cli.rb +45 -0
- data/lib/pipeline_toolkit/commands/msg_probe/cli.rb +46 -0
- data/lib/pipeline_toolkit/commands/msg_push/cli.rb +58 -0
- data/lib/pipeline_toolkit/commands/msg_sink/cli.rb +41 -0
- data/lib/pipeline_toolkit/commands/msg_subscribe/cli.rb +58 -0
- data/lib/pipeline_toolkit/default_logger.rb +126 -11
- data/lib/pipeline_toolkit/handlers/message_handler.rb +38 -0
- data/lib/pipeline_toolkit/message_coder.rb +18 -8
- data/lib/pipeline_toolkit/message_command.rb +138 -61
- data/lib/pipeline_toolkit/message_generator.rb +21 -0
- data/lib/pipeline_toolkit/message_probe.rb +6 -6
- data/lib/pipeline_toolkit/message_pusher.rb +51 -54
- data/lib/pipeline_toolkit/message_sink.rb +1 -1
- data/lib/pipeline_toolkit/message_subscriber.rb +182 -201
- data/lib/pipeline_toolkit/monitoring/monitor_server.rb +124 -0
- data/spec/eventmachine_helper.rb +44 -0
- data/spec/message_subscriber_spec.rb +64 -0
- data/spec/spec_helper.rb +15 -0
- metadata +202 -47
- data/.gitignore +0 -5
- data/README.rdoc +0 -70
- data/Rakefile +0 -40
- data/VERSION +0 -1
- data/bin/msg_generator.rb +0 -0
- data/bin/msg_probe.rb +0 -15
- data/bin/msg_push.rb +0 -25
- data/bin/msg_sink.rb +0 -11
- data/bin/msg_subscribe.rb +0 -27
- data/monitor/munin.rb +0 -91
- data/pipeline_toolkit.gemspec +0 -72
data/LICENSE.markdown
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Visfleet Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Pipeline Toolkit #
|
2
|
+
by VisFleet
|
3
|
+
|
4
|
+
Command line tools for processing messages by constructing a pipeline of workers. [AMQP](http://amqp.rubyforge.org/ "AMQP") and Unix pipes are used to construct the pipeline. Messages are simple Hashes (serialized) so they can hold any values and change throughout the processing.
|
5
|
+
|
6
|
+
Provides:
|
7
|
+
|
8
|
+
* Processing acknowledgments, ensuring the a message is only disposed of once it has been successful processed
|
9
|
+
* Performance. Messages are moved through the pipeline fast
|
10
|
+
* Command line tools for:
|
11
|
+
* Subscribing to messages from an [AMQP queue](http://amqp.rubyforge.org/classes/MQ/Queue.html "MQ::Queue")
|
12
|
+
* Pushing messages back onto an [AMQP exchange](http://amqp.rubyforge.org/classes/MQ/Exchange.html "MQ::Exchange")
|
13
|
+
* Monitoring performance (see msg_probe)
|
14
|
+
* A base module ({MessageCommand}) to include into your own classes to quickly make workers.
|
15
|
+
|
16
|
+
## Install ##
|
17
|
+
|
18
|
+
> (sudo) gem install pipeline_toolkit
|
19
|
+
|
20
|
+
### Dependancies ###
|
21
|
+
|
22
|
+
It is assumed that you have:
|
23
|
+
- An [AMQP](http://amqp.rubyforge.org/ "AMQP") message server to pop and push messages to (e.g. http://www.rabbitmq.com/)
|
24
|
+
- A *nix system, such as Linux or Mac OS X.
|
25
|
+
|
26
|
+
## Usage ##
|
27
|
+
|
28
|
+
1. Create your worker
|
29
|
+
|
30
|
+
class MyMachine
|
31
|
+
include MessageCommand
|
32
|
+
|
33
|
+
def initialize_machine
|
34
|
+
# Optional: setup any dependencies required by your machine
|
35
|
+
end
|
36
|
+
|
37
|
+
def report_back
|
38
|
+
# Optional: write information about the pipeline back
|
39
|
+
# through the acknowledgement pipe
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_standard(message)
|
43
|
+
# Required: handle the message within your machine
|
44
|
+
unless failed_to_process?
|
45
|
+
pass_on(message) # or alternatively acknowledge if this
|
46
|
+
# is the last machine in the pipeline.
|
47
|
+
else
|
48
|
+
# handle the failed message here (however you deem fit)
|
49
|
+
acknowledge(message)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
MyMachine.new.start
|
55
|
+
|
56
|
+
2. Hook it up to a [AMQP](http://amqp.rubyforge.org/ "AMQP") message source
|
57
|
+
|
58
|
+
> msg_subscribe -x raw -t topic -q octane | my_worker.rb | msg_push -x standard -q standard
|
59
|
+
|
60
|
+
You can learn more about the command line tools and what options are available by using their help command.
|
61
|
+
|
62
|
+
> msg_subscriber --help
|
63
|
+
> msg_push --help
|
64
|
+
> msg_sink --help
|
65
|
+
> msg_probe --help
|
66
|
+
|
67
|
+
## Examples ##
|
68
|
+
|
69
|
+
In the example, open two terminal windows and then execute the following commands in each:
|
70
|
+
|
71
|
+
> msg_generator | msg_push -x test-exchange
|
72
|
+
> msg_subscribe -a false --http-port 9090 -x test-exchange -q test_queue > /dev/null
|
73
|
+
|
74
|
+
The example does the following:
|
75
|
+
|
76
|
+
1. Generate a bunch of sample messages
|
77
|
+
2. Push them to an [AMQP exchange](http://amqp.rubyforge.org/classes/MQ/Exchange.html "MQ::Exchange")
|
78
|
+
'test-exchange'.
|
79
|
+
3. Hook up a pipe to consume the generated messages
|
80
|
+
4. Push results to /dev/null.
|
81
|
+
5. Goto http://localhost:9090 to see message throughput.
|
82
|
+
|
83
|
+
Now lets switch on acknowledgements:
|
84
|
+
|
85
|
+
> msg_generator | msg_push -x test-exchange
|
86
|
+
> msg_subscribe -x test-exchange -q test_queue | msg_sink
|
87
|
+
|
88
|
+
This example does the same as above, but this time with acknowledgements switched on.
|
89
|
+
This guarantees that a message isn't removed from the message server until handled.
|
90
|
+
msg_sink acknowledges all messages.
|
91
|
+
|
92
|
+
## Todo ##
|
93
|
+
|
94
|
+
* DNS-SD is broken. See http://github.com/tenderlove/dnssd/issues#issue/3. We need to fix it or kill it.
|
95
|
+
|
96
|
+
* Write units tests.
|
97
|
+
|
98
|
+
* Tidy up logging. Not used consistently throughout code. What do we want to log?
|
data/bin/msg_generator
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created on 2010-3-17.
|
4
|
+
# Copyright Visfleet Ltd. (c) 2010. All rights reserved.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/pipeline_toolkit'
|
8
|
+
require "pipeline_toolkit/commands/msg_generator/cli"
|
9
|
+
|
10
|
+
# print an options summary if no args specified
|
11
|
+
ARGV << "--help" if ARGV.empty?
|
12
|
+
|
13
|
+
Commands::MsgGenerate::CLI.execute(STDOUT, ARGV)
|
data/bin/msg_probe
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created on 2010-3-17.
|
4
|
+
# Copyright Visfleet Ltd. (c) 2010. All rights reserved.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/pipeline_toolkit'
|
8
|
+
require 'pipeline_toolkit/commands/msg_probe/cli'
|
9
|
+
|
10
|
+
# print an options summary if no args specified
|
11
|
+
ARGV << "--help" if ARGV.empty?
|
12
|
+
|
13
|
+
Commands::MsgProbe::CLI.execute(STDOUT, ARGV)
|
data/bin/msg_push
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created on 2010-3-17.
|
4
|
+
# Copyright Visfleet Ltd. (c) 2010. All rights reserved.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/pipeline_toolkit'
|
8
|
+
require "pipeline_toolkit/commands/msg_push/cli"
|
9
|
+
|
10
|
+
# print an options summary if no args specified
|
11
|
+
ARGV << "--help" if ARGV.empty?
|
12
|
+
|
13
|
+
Commands::MsgPush::CLI.execute(STDOUT, ARGV)
|
data/bin/msg_sink
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created on 2010-3-17.
|
4
|
+
# Copyright Visfleet Ltd. (c) 2010. All rights reserved.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/pipeline_toolkit'
|
8
|
+
require "pipeline_toolkit/commands/msg_sink/cli"
|
9
|
+
|
10
|
+
# print an options summary if no args specified
|
11
|
+
ARGV << "--help" if ARGV.empty?
|
12
|
+
|
13
|
+
Commands::MsgSink::CLI.execute(STDOUT, ARGV)
|
14
|
+
|
data/bin/msg_subscribe
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created on 2010-3-17.
|
4
|
+
# Copyright Visfleet Ltd. (c) 2010. All rights reserved.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/pipeline_toolkit'
|
8
|
+
require "pipeline_toolkit/commands/msg_subscribe/cli"
|
9
|
+
|
10
|
+
# print an options summary if no args specified
|
11
|
+
ARGV << "--help" if ARGV.empty?
|
12
|
+
|
13
|
+
Commands::MsgSubscribe::CLI.execute(STDOUT, ARGV)
|
data/lib/pipeline_toolkit.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require 'pipeline_toolkit/amqp/abstract'
|
4
|
+
require 'pipeline_toolkit/amqp/reader'
|
5
|
+
require 'pipeline_toolkit/amqp/writer'
|
6
|
+
|
7
|
+
require 'pipeline_toolkit/monitoring/monitor_server'
|
8
|
+
|
9
|
+
require 'pipeline_toolkit/handlers/message_handler'
|
10
|
+
|
1
11
|
require "pipeline_toolkit/default_logger"
|
2
12
|
require "pipeline_toolkit/message_coder"
|
3
13
|
require "pipeline_toolkit/message_command"
|
@@ -7,3 +17,10 @@ require "pipeline_toolkit/message_subscriber"
|
|
7
17
|
require "pipeline_toolkit/message_sink"
|
8
18
|
require "pipeline_toolkit/open_hash"
|
9
19
|
require "pipeline_toolkit/socket_util"
|
20
|
+
require 'pipeline_toolkit/message_generator'
|
21
|
+
|
22
|
+
require 'pipeline_toolkit/commands/msg_subscribe/cli'
|
23
|
+
require 'pipeline_toolkit/commands/msg_generator/cli'
|
24
|
+
require 'pipeline_toolkit/commands/msg_probe/cli'
|
25
|
+
require 'pipeline_toolkit/commands/msg_push/cli'
|
26
|
+
require 'pipeline_toolkit/commands/msg_sink/cli'
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'mq'
|
2
|
+
|
3
|
+
module Amqp # :nodoc:
|
4
|
+
|
5
|
+
##
|
6
|
+
# Provides abstract base functionality used in both {Amqp::Reader} and {Amqp::Writer}
|
7
|
+
#
|
8
|
+
module Abstract
|
9
|
+
|
10
|
+
##
|
11
|
+
# Getter for the options hash
|
12
|
+
#
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
##
|
16
|
+
# Initialize a new instance of either the {Amqp::Reader} or {Amqp::Writer}
|
17
|
+
#
|
18
|
+
# @param options<Hash> The options hash
|
19
|
+
# @option options [Symbol] :host ('localhost') The AMQP server address for the AMQP server.
|
20
|
+
# @option options [Symbol] :port (5672) The AMQP server port for the AMQP server.
|
21
|
+
# @option options [Symbol] :user ('guest') The username as defined by the AMQP server.
|
22
|
+
# @option options [Symbol] :pass ('guest') The password for the associated :user as defined by the AMQP server.
|
23
|
+
# @option options [Symbol] :vhost ('/') The virtual host as defined by the AMQP server.
|
24
|
+
# @option options [Symbol] :type ('fanout') The exchange type (direct, fanout or topic).
|
25
|
+
# @option options [Symbol] :exchange ('') The exchange name
|
26
|
+
# @option options [Symbol] :durable (false) If set to true, the exchange will be marked as durable.
|
27
|
+
# @option options [Symbol] :passive (false) If set to true, the server will not create the exchange if it does not already exist.
|
28
|
+
# @option options [Symbol] :ack (true) If this field is set to false the server does not expect acknowledgments for messages.
|
29
|
+
# @option options [Symbol] :env ('development') The environment to run (development, production).
|
30
|
+
#
|
31
|
+
def initialize(options = {})
|
32
|
+
super(options)
|
33
|
+
|
34
|
+
DefaultLogger.init_logger(options)
|
35
|
+
|
36
|
+
@options = options
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Create a new connection to the AMQP server.
|
41
|
+
#
|
42
|
+
def initialize_connection
|
43
|
+
DefaultLogger.debug("Amqp::Abstract#initialize_connection") if options[:env] == "development"
|
44
|
+
@connection = AMQP.connect(options.select_keys(:host, :port, :user, :pass, :vhost))
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Returns a new channel. A channel is a bidirectional virtual connection between the client
|
49
|
+
# and the AMQP server.
|
50
|
+
#
|
51
|
+
def initialize_channel
|
52
|
+
DefaultLogger.debug("Amqp::Abstract#initialize_channel") if options[:env] == "development"
|
53
|
+
@channel = MQ.new(@connection)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Defines, intializes and returns an Exchange
|
58
|
+
# to act as an ingress point for all published messages.
|
59
|
+
#
|
60
|
+
def initialize_exchange
|
61
|
+
DefaultLogger.debug("Amqp::Abstract#initialize_exchange") if options[:env] == "development"
|
62
|
+
# declare a exchange on the channel
|
63
|
+
@exchange = MQ::Exchange.new(@channel, options[:type], options[:exchange], :durable => options[:durable], :passive => options[:passive])
|
64
|
+
rescue MQ::Error => e # rescued here because main thread does not seem to see it
|
65
|
+
DefaultLogger.error "#{e.class.name}: #{e.message}\n" << e.backtrace.join("\n")
|
66
|
+
raise e
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Defines, intializes and returns an Queue that store and forward messages.
|
71
|
+
#
|
72
|
+
# @param name<String> The name to use for the queue
|
73
|
+
#
|
74
|
+
def initialize_queue(name = '')
|
75
|
+
DefaultLogger.debug("Amqp::Abstract#initialize_queue(name = '')") if options[:env] == "development"
|
76
|
+
name = options[:queue] if name.nil? || name.empty?
|
77
|
+
@queue = MQ::Queue.new(@channel, name, :durable => options[:durable], :passive => options[:passive])
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Binds the queue to an exchange.
|
82
|
+
#
|
83
|
+
# @param routing_key<Sting> Specifies the routing key for the binding. The routing key is used for
|
84
|
+
# routing messages depending on the exchange configuration.
|
85
|
+
#
|
86
|
+
def bind_queue(routing_key = '')
|
87
|
+
DefaultLogger.debug("Amqp::Abstract#bind_queue(routing_key = '')") if options[:env] == "development"
|
88
|
+
unless routing_key.nil? || routing_key.empty?
|
89
|
+
@queue.bind(@exchange, :key => routing_key)
|
90
|
+
else
|
91
|
+
@queue.bind(@exchange)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'pipeline_toolkit/amqp/abstract'
|
2
|
+
|
3
|
+
module Amqp # :nodoc:
|
4
|
+
|
5
|
+
##
|
6
|
+
# The Reader provides functionality specific to asynchronous message
|
7
|
+
# delivery by subscribing to the AMQP server.
|
8
|
+
#
|
9
|
+
module Reader
|
10
|
+
include Amqp::Abstract
|
11
|
+
|
12
|
+
##
|
13
|
+
# Initialize the AMQP server specific to handling
|
14
|
+
# of messages from the server.
|
15
|
+
#
|
16
|
+
def initialize_reader
|
17
|
+
DefaultLogger.debug("Amqp::Reader#initialize_reader") if options[:env] == "development"
|
18
|
+
@ack_headers ||= {}
|
19
|
+
initialize_connection
|
20
|
+
initialize_channel
|
21
|
+
@channel.prefetch(1) # We only want to handle one message at a time
|
22
|
+
initialize_exchange
|
23
|
+
initialize_queue
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Subscribe the queue to receive messages
|
28
|
+
#
|
29
|
+
def queue_subscribe
|
30
|
+
DefaultLogger.debug("Amqp::Reader#queue_subscribe") if options[:env] == "development"
|
31
|
+
unless AMQP.closing?
|
32
|
+
@queue.subscribe(:ack => options[:ack]) do |header, body|
|
33
|
+
DefaultLogger.debug("Rabbit Message: #{body}") if options[:env] == "development"
|
34
|
+
process_queue_message(header, body)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Store the acknowledgement header
|
41
|
+
#
|
42
|
+
# @param message<Hash> The message
|
43
|
+
# @param header<MQ::Header> The message queue header for the message
|
44
|
+
#
|
45
|
+
def store_acknowledgement(message, header)
|
46
|
+
DefaultLogger.debug("Amqp::Reader#store_acknowledgement(message, header)") if options[:env] == "development"
|
47
|
+
message[:ack_id] = header.delivery_tag.to_s
|
48
|
+
@ack_headers[message[:ack_id]] = header
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Perform the acknowledgement on the stored header to
|
53
|
+
# tell AMQP server we are done with the message.
|
54
|
+
#
|
55
|
+
# @param ack_id<String> The acknowledgement identifier
|
56
|
+
#
|
57
|
+
def perform_acknowledgement(ack_id)
|
58
|
+
DefaultLogger.debug("Amqp::Reader#perform_acknowledgement(ack_id)") if options[:env] == "development"
|
59
|
+
header = @ack_headers.delete(ack_id)
|
60
|
+
header.ack
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'pipeline_toolkit/amqp/abstract'
|
2
|
+
require 'pipeline_toolkit/message_coder'
|
3
|
+
|
4
|
+
module Amqp # :nodoc:
|
5
|
+
|
6
|
+
##
|
7
|
+
# The Writer provides functionality specific to asynchronous message
|
8
|
+
# publishing to the AMQP server.
|
9
|
+
#
|
10
|
+
module Writer
|
11
|
+
include Amqp::Abstract
|
12
|
+
|
13
|
+
##
|
14
|
+
# Initialize the AMQP server specific to handling
|
15
|
+
# of messages publishing to the server.
|
16
|
+
#
|
17
|
+
def initialize_writer
|
18
|
+
DefaultLogger.debug("Amqp::Writer#initialize_writer") if options[:env] == "development"
|
19
|
+
initialize_connection
|
20
|
+
initialize_channel
|
21
|
+
initialize_exchange
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Initializes the queues to publish the messages too.
|
26
|
+
#
|
27
|
+
def initialize_queues
|
28
|
+
DefaultLogger.debug("Amqp::Writer#initialize_queues") if options[:env] == "development"
|
29
|
+
options[:queues].each do |name, routing_key|
|
30
|
+
initialize_queue(name)
|
31
|
+
bind_queue(routing_key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Handles the publishing of messages into the AMQP server.
|
37
|
+
#
|
38
|
+
# @param message<Hash> The message to publish
|
39
|
+
#
|
40
|
+
def publish(message)
|
41
|
+
DefaultLogger.debug("Amqp::Writer#publish(message)") if options[:env] == "development"
|
42
|
+
if message.has_key?(:routing_key)
|
43
|
+
@exchange.publish(MessageCoder.encode(message), :key => message[:routing_key])
|
44
|
+
else
|
45
|
+
@exchange.publish(MessageCoder.encode(message))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def queue_names
|
50
|
+
options[:queues].map { |name, type| name }
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'trollop'
|
3
|
+
require 'eventmachine'
|
4
|
+
|
5
|
+
Signal.trap('INT') do
|
6
|
+
# puts "\nStopping"
|
7
|
+
# TODO: complete signal trap interrupt
|
8
|
+
end
|
9
|
+
|
10
|
+
Signal.trap('TERM') do
|
11
|
+
# puts "\nStopping"
|
12
|
+
# TODO: complete signal trap terminate
|
13
|
+
end
|
14
|
+
|
15
|
+
module Commands # :nodoc:
|
16
|
+
module MsgGenerate
|
17
|
+
class CLI
|
18
|
+
def self.execute(stdout, arguments=[])
|
19
|
+
|
20
|
+
opts = Trollop::options do
|
21
|
+
banner <<-EOL
|
22
|
+
Message Subscriber
|
23
|
+
------------------
|
24
|
+
Generates messages for testing the pipeline. Messages are specified
|
25
|
+
using JSON.
|
26
|
+
|
27
|
+
Usage:
|
28
|
+
msg_generator [options]
|
29
|
+
|
30
|
+
Examples:
|
31
|
+
msg_generator -m '{"id":1, "firstName":"John Smith"}'
|
32
|
+
|
33
|
+
Options:
|
34
|
+
EOL
|
35
|
+
opt :msg, "The message to send", :short => "m", :default => '{"id":1}'
|
36
|
+
opt :delay, "Sleep time between sends in seconds", :short => "d", :type => :float
|
37
|
+
|
38
|
+
opt :env, "The environment to run (development, production)", :default => "development", :short => :e
|
39
|
+
end
|
40
|
+
|
41
|
+
MessageGenerator.new(opts).start
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|