pipeline_toolkit 1.0.4 → 1.0.6
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/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
|