visfleet-pipeline_toolkit 0.0.1 → 0.1.0

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/Rakefile CHANGED
@@ -5,11 +5,11 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "pipeline_toolkit"
8
- gem.summary = %Q{TODO}
9
- gem.email = "aisha.fenton@visfleet.com"
8
+ gem.summary = %Q{Toolkit for building processing pipelines using Unix Pipes and AMQP messages}
9
+ gem.email = "labs@visfleet.com"
10
10
  gem.homepage = "http://github.com/visfleet/pipeline_toolkit"
11
11
  gem.authors = ["Aisha Fenton"]
12
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
12
+ gem.executables = ["msg_probe.rb", "msg_subscribe.rb", "msg_push.rb", "msg_pop.rb", "msg_sink.rb"]
13
13
  end
14
14
 
15
15
  rescue LoadError
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
File without changes
@@ -8,4 +8,4 @@ opts = Trollop::options do
8
8
  opt :interval, "Interval", :short => "i", :default => 100
9
9
  end
10
10
 
11
- MessageMonitor.new(opts).start
11
+ MessageProbe.new(opts).start
data/bin/msg_push.rb ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'trollop'
5
+ require 'pipeline_toolkit'
6
+
7
+ opts = Trollop::options do
8
+ opt :exchanges, "The destination exchange(s)", :short => "x", :type => :strings
9
+ opt :key_eval, "A string of ruby code that is evaluated to produce a routing key for a given message.
10
+ By default each message has no routing key", :short => "e", :type => :string
11
+ opt :key_file, "A ruby file that gets included which contains a custom route_key method", :short => "f", :type => :string
12
+
13
+ # Msg server
14
+ opt :host, "The AMQP message server host", :default => "localhost"
15
+ opt :port, "The AMQP message server port", :default => "5672"
16
+ opt :user, "The AMQP message server username", :default => "guest"
17
+ opt :pass, "The AMQP message server username", :default => "guest"
18
+ opt :vhost, "The AMQP message server vhost", :default => "/"
19
+ end
20
+
21
+ mp = MessagePusher.new(opts)
22
+ # FIXME. Should be in MessageCommand class
23
+ Signal.trap('INT') { mp.stop }
24
+ Signal.trap('TERM'){ mp.stop }
25
+ mp.start
data/bin/msg_sink.rb ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'trollop'
5
+ require 'pipeline_toolkit'
6
+
7
+ # opts = Trollop::options do
8
+ # opt :interval, "Interval", :short => "i", :default => 100
9
+ # end
10
+
11
+ MessageSink.new.start
@@ -5,9 +5,11 @@ require 'trollop'
5
5
  require 'pipeline_toolkit'
6
6
 
7
7
  opts = Trollop::options do
8
- opt :sources, "Sources", :short => "s", :type => :strings
8
+ opt :exchange, "The exchange to subscribe to", :short => "x", :type => :string
9
+ opt :queue, "The source queue", :short => "q", :type => :string
9
10
  opt :ack, "Switch that requires that messages are successfully processed before continuing with the next message", :short => "a"
10
- opt :queue_name, "The name that the created queue is given", :short => "q", :type => :string
11
+ opt :topic, "The queue topic to subscribe to", :short => "t", :type => :string
12
+ opt :max_unackd, "The maximum number of unaknowledged messages to buffer before waiting for them to be acknowledged. Defaults to 100", :default => 100
11
13
 
12
14
  # Msg server
13
15
  opt :host, "The AMQP message server host", :default => "localhost"
@@ -17,7 +19,4 @@ opts = Trollop::options do
17
19
  opt :vhost, "The AMQP message server vhost", :default => "/"
18
20
  end
19
21
 
20
- ms = MessageSubscriber.new(opts)
21
- Signal.trap('INT') { ms.stop }
22
- Signal.trap('TERM'){ ms.stop }
23
- ms.start
22
+ ms = MessageSubscriber.new(opts).start
@@ -0,0 +1,9 @@
1
+ require "pipeline_toolkit/central_logger"
2
+ require "pipeline_toolkit/message_coder"
3
+ require "pipeline_toolkit/message_command"
4
+ require "pipeline_toolkit/message_probe"
5
+ require "pipeline_toolkit/message_popper"
6
+ require "pipeline_toolkit/message_pusher"
7
+ require "pipeline_toolkit/message_subscriber"
8
+ require "pipeline_toolkit/message_sink"
9
+ require "pipeline_toolkit/open_hash"
@@ -0,0 +1,19 @@
1
+
2
+ # Encodes messages
3
+ #
4
+ class MessageCoder
5
+
6
+ def self.encode(msg)
7
+ # NB: Using Marshal here because it's 9-10x faster than to_yaml
8
+ # See http://gist.github.com/190849
9
+ str = Marshal.dump(msg)
10
+ str.gsub!("\n", '--\\n')
11
+ str
12
+ end
13
+
14
+ def self.decode(str)
15
+ str.gsub!('--\\n', "\n")
16
+ Marshal.load(str)
17
+ end
18
+
19
+ end
@@ -0,0 +1,96 @@
1
+ require "rubygems"
2
+ require "eventmachine"
3
+
4
+ module MessageCommand
5
+ include DefaultLogging
6
+
7
+ attr_reader :sys_pipe
8
+
9
+ def start
10
+ log.info("starting")
11
+
12
+ Signal.trap('INT') { EM.stop }
13
+ Signal.trap('TERM'){ EM.stop }
14
+
15
+ @ack_buffer ||= ""
16
+
17
+ begin
18
+ EM.run do
19
+ self.init_loop
20
+ EM.attach($stdin, ProcessLine, self)
21
+ end
22
+ rescue StandardError => e
23
+ log.info e
24
+ raise e
25
+ ensure
26
+ self.shutdown
27
+ end
28
+ end
29
+
30
+ def shutdown
31
+ log.info("shutting down")
32
+ @sys_pipe && @sys_pipe.close
33
+ end
34
+
35
+ def process_line(line)
36
+ msg = MessageCoder.decode(line)
37
+
38
+ case msg[:msg_type]
39
+ when :system
40
+ result = process_system(msg)
41
+ else
42
+ result = process_message(msg)
43
+ end
44
+
45
+ case result
46
+ when :ack
47
+ self.ack_msg(msg)
48
+ else
49
+ self.pass_on_msg(result)
50
+ end
51
+ end
52
+
53
+ def ack_msg(msg)
54
+ return unless @use_ack
55
+ @sys_pipe.syswrite(msg.ack_id + "\n")
56
+ end
57
+
58
+ def pass_on_msg(msg)
59
+ $stdout.syswrite(MessageCoder.encode(msg) << "\n")
60
+ end
61
+
62
+ # Override in included class. Provides a chance to initialize any
63
+ # code that needs to take place once the EM loop has started.
64
+ def init_loop
65
+ # Implemented in class that includes me
66
+ end
67
+
68
+ # Override in included class. Processes a message. This method
69
+ # must return either a msg object -- which may or may not have been modified -- or the symbol :ack.
70
+ # Returning :ack mean that the message has been dealt with and can be acknowledged back to the queue
71
+ # server. All messages must be acknowledged by at least one message_command.
72
+ def process_message(msg)
73
+ # Implemented in class that includes me
74
+ msg
75
+ end
76
+
77
+ def process_system(msg)
78
+ @sys_pipe = File.open(msg.sys_pipe, "w")
79
+ @use_ack = msg.use_ack
80
+ @max_unackd = msg.max_unackd
81
+ msg
82
+ end
83
+
84
+ module ProcessLine
85
+ include DefaultLogging
86
+
87
+ def initialize(msg_command)
88
+ @msg_command = msg_command
89
+ end
90
+
91
+ def notify_readable
92
+ @msg_command.process_line($stdin.gets)
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,87 @@
1
+ require "eventmachine"
2
+ require "bunny"
3
+ require "time"
4
+
5
+ class MessagePopper
6
+ include DefaultLogging
7
+
8
+ PIPE_PATH = "/tmp"
9
+
10
+ def initialize(opts)
11
+ @cycle = opts[:cycle]
12
+ @msg_server = Bunny.new({:spec => '08'}.merge!(opts.select_keys(:host, :port, :user, :pass, :vhost)))
13
+ @msg_server.start
14
+ @sources = opts[:sources]
15
+ @use_ack = opts[:ack]
16
+ end
17
+
18
+ def start
19
+ self.create_sys_pipe
20
+ EM.run do
21
+ EM.add_periodic_timer(@cycle) { self.tick }
22
+ end
23
+ self.destroy_sys_pipe
24
+ end
25
+
26
+ def create_sys_pipe
27
+ log.debug("creating sys-pipe")
28
+ name = File.join(PIPE_PATH, "sys_pipe_#{self.generate_guid}")
29
+ `mkfifo #{name}`
30
+ @sys_pipe = File.new(name, "r+")
31
+ sleep(2)
32
+ $stdout.puts(MessageCoder.encode({:msg_type => :system, :sys_pipe => name, :use_ack => @use_ack}))
33
+ $stdout.flush
34
+ end
35
+
36
+ def destroy_sys_pipe
37
+ `rm #{@sys_pipe}`
38
+ end
39
+
40
+ def generate_guid
41
+ # TODO maybe better way to do guid
42
+ "#{Time.now.iso8601}_#{rand(99999)}_#{rand(99999)}_#{rand(99999)}"
43
+ end
44
+
45
+ def tick
46
+ log.debug("draining queue")
47
+ loop do
48
+ q_empty = true
49
+ @sources.each do |source|
50
+ # FIXME. @queue for each source, or not needed
51
+ @queue ||= @msg_server.queue(source)
52
+ result = @queue.pop(:ack => @use_ack)
53
+ next if result == :queue_empty
54
+ # msg = YAML.load(result)
55
+ q_empty = false
56
+ # @use_ack ? verify(msg, source) { write_msg(msg) } : write_msg(msg)
57
+
58
+ @count ||= 0
59
+ @count += 1
60
+ @prev_time ||= Time.now
61
+ if @count > 100
62
+ t = Time.now
63
+ log.debug("per sec #{@count / (t - @prev_time)}")
64
+ @prev_time = t
65
+ @count = 0
66
+ end
67
+
68
+ end
69
+ break if q_empty
70
+ end
71
+ end
72
+
73
+ def write_msg(msg)
74
+ $stdout.puts(MessageCoder.encode(msg))
75
+ $stdout.flush
76
+ end
77
+
78
+ def verify(msg, source)
79
+ msg.ack_id = generate_guid
80
+ yield
81
+ $stdout.flush
82
+ ack_id = @sys_pipe.gets.chomp!
83
+ raise Exception.new("ACK failed with msg #{msg.to_yaml}") unless msg.ack_id == ack_id
84
+ @msg_server.queue(source).ack
85
+ end
86
+
87
+ end
@@ -0,0 +1,24 @@
1
+ class MessageProbe
2
+ include MessageCommand
3
+
4
+ def initialize(opts)
5
+ @interval = opts.interval
6
+ reset
7
+ end
8
+
9
+ def process_message(msg)
10
+ @count += 1
11
+ if @count > @interval
12
+ delta = Time.now - @prev_time
13
+ log.info("#{@count / delta} msgs per second")
14
+ reset
15
+ end
16
+ msg
17
+ end
18
+
19
+ def reset
20
+ @count = 0
21
+ @prev_time = Time.now
22
+ end
23
+
24
+ end
@@ -0,0 +1,54 @@
1
+ require "mq"
2
+
3
+ class MessagePusher
4
+ include MessageCommand
5
+
6
+ def initialize(opts)
7
+ @key_eval = opts.key_eval
8
+ if opts.key_file
9
+ @key_file = opts.key_file
10
+ load_route(@key_file)
11
+ self.init_route
12
+ end
13
+ @exchange_names = opts.exchanges.map { |str| str.split(":") }
14
+ @msg_server_config = opts.select_keys(:host, :port, :user, :pass, :vhost)
15
+ end
16
+
17
+ def init_loop
18
+ @msg_server = MQ.new(AMQP.connect(@msg_server_config))
19
+ self.setup_exchanges
20
+ end
21
+
22
+ def setup_exchanges
23
+ @exchanges = []
24
+ @exchange_names.each do |name, type|
25
+ type ||= :fanout
26
+ @exchanges << MQ::Exchange.new(@msg_server, type.to_sym, name)
27
+ end
28
+ end
29
+
30
+ def load_route(key_file)
31
+ require key_file
32
+ self.extend eval(classify(key_file.gsub(".rb", "")))
33
+ end
34
+
35
+ # Stolen from rails.
36
+ def classify(str)
37
+ str.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
38
+ end
39
+
40
+ # is overriden by included fork_file if specified
41
+ def route_key(msg)
42
+ @key_eval ? eval(@key_eval) : nil
43
+ end
44
+
45
+ def process_message(msg)
46
+ @exchanges.each do |exchange|
47
+ key = route_key(msg)
48
+ exchange.publish(MessageCoder.encode(msg), :routing_key => key)
49
+ # exchange.publish(msg.to_yaml, :routing_key => key)
50
+ end
51
+ :ack
52
+ end
53
+
54
+ end
@@ -0,0 +1,8 @@
1
+ class MessageSink
2
+ include MessageCommand
3
+
4
+ def process_message(msg)
5
+ :ack
6
+ end
7
+
8
+ end
@@ -0,0 +1,134 @@
1
+ require "eventmachine"
2
+ require "mq"
3
+ require "time"
4
+ require "socket"
5
+
6
+ class MessageSubscriber
7
+ include DefaultLogging
8
+
9
+ PIPE_PATH = "/tmp"
10
+
11
+ def initialize(opts)
12
+ @exchange_name = opts[:exchange]
13
+ @queue_name = opts[:queue]
14
+ @use_ack = opts[:ack]
15
+ @topic = opts[:topic]
16
+ @msg_server_opts = opts.select_keys(:host, :port, :user, :pass, :vhost)
17
+ @unackd_msgs = {}
18
+ @max_unackd = opts[:max_unackd]
19
+ end
20
+
21
+ def start
22
+ Signal.trap('INT') { AMQP.stop{ EM.stop } }
23
+ Signal.trap('TERM'){ AMQP.stop{ EM.stop } }
24
+
25
+ begin
26
+ self.create_sys_pipe
27
+ AMQP.start(@msg_server_opts) do
28
+ # For ack to work appropriatly you must shutdown AMQP gracefully,
29
+ # otherwise all items in your queue will be returned
30
+ # FIXME. Doesn't shut down cleanly with these commands included. Why?
31
+
32
+ self.setup_queue
33
+ # NB. prefetch limits the amount of unknowledged messages that come down the pipe.
34
+ MQ.prefetch(@max_unackd)
35
+ @queue.subscribe(:ack => @use_ack) do |header, body|
36
+ self.process_msg(header, body)
37
+ end
38
+
39
+ EM.attach(@sys_pipe, HandleAcks, @sys_pipe, @unackd_msgs)
40
+ end
41
+ rescue StandardError => e
42
+ log.info e
43
+ raise e
44
+ ensure
45
+ self.shutdown
46
+ end
47
+ end
48
+
49
+ def shutdown
50
+ log.info "Shutting down"
51
+ self.destroy_sys_pipe
52
+ end
53
+
54
+ def setup_queue
55
+ # If a queue_name is given then we treat the queue as fixed, otherwise as temporary
56
+ @queue = @queue_name ? MQ.queue(@queue_name, :durable => true) :
57
+ self.generate_temporary_queue
58
+ if @exchange_name
59
+ log.info("Binding to exchange:#{@exchange_name} #{@topic ? "using topic:" + @topic : ""}")
60
+ # OPTIMIZE. Should we be setting up the exchange just incase it hasn't been created yet?
61
+ @queue.bind(@exchange_name, :key => @topic)
62
+ end
63
+ end
64
+
65
+ def create_sys_pipe
66
+ log.debug("creating sys-pipe")
67
+ name = File.join(PIPE_PATH, "sys_pipe_#{self.generate_guid}")
68
+ `mkfifo #{name}`
69
+ @sys_pipe = File.new(name, "r+")
70
+ $stdout.puts(MessageCoder.encode({:msg_type => :system,
71
+ :sys_pipe => name,
72
+ :use_ack => @use_ack,
73
+ :max_unackd => @max_unackd}))
74
+ $stdout.flush
75
+ end
76
+
77
+ def destroy_sys_pipe
78
+ `rm #{@sys_pipe.path}`
79
+ end
80
+
81
+ def generate_temporary_queue
82
+ qname = "#{Socket.gethostname}_#{self.generate_guid}"
83
+ log.debug("Binding temporary queue #{qname}")
84
+ MQ.queue(qname, :auto_delete => true, :durable => false)
85
+ end
86
+
87
+ # Generates a guid. Stolen from EM.
88
+ def generate_guid
89
+ # Cache uuidgen seed for better performance
90
+ if @ix and @ix >= 10_000
91
+ @ix = nil
92
+ @seed = nil
93
+ end
94
+
95
+ # NB. This will only work on *nix platforms
96
+ @seed ||= `uuidgen`.chomp.gsub(/-/,"")
97
+ @ix ||= 0
98
+
99
+ "#{@seed}#{@ix += 1}"
100
+ end
101
+
102
+ def process_msg(header, body)
103
+ msg = YAML.load(body)
104
+ store_ack(msg, header) if @use_ack
105
+ write_msg(msg)
106
+ end
107
+
108
+ def write_msg(msg)
109
+ $stdout.syswrite(MessageCoder.encode(msg) << "\n")
110
+ end
111
+
112
+ def store_ack(msg, header)
113
+ msg.ack_id = header.delivery_tag.to_s
114
+ @unackd_msgs[msg.ack_id] = header
115
+ end
116
+
117
+ # Handles msg acks
118
+ module HandleAcks
119
+ include DefaultLogging
120
+
121
+ def initialize(sys_pipe, unackd_msgs)
122
+ @sys_pipe = sys_pipe
123
+ @unackd_msgs = unackd_msgs
124
+ end
125
+
126
+ def notify_readable
127
+ ack_id = @sys_pipe.gets.chomp!
128
+ header = @unackd_msgs.delete(ack_id)
129
+ header.ack
130
+ end
131
+ end
132
+
133
+ end
134
+
@@ -0,0 +1,24 @@
1
+ # Stolen from
2
+ # http://github.com/karottenreibe/ohash/
3
+ module OpenHash
4
+ def method_missing(meth, *args)
5
+ method = meth.to_s
6
+
7
+ if method =~ %r{.+=$}
8
+ super unless args.length == 1
9
+ self[method[0...-1].to_sym] = args.first
10
+ else
11
+ self[meth]
12
+ end
13
+ end
14
+
15
+ def select_keys(*keys)
16
+ h = {}
17
+ self.each do |key, value|
18
+ h[key] = value if keys.include?(key)
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ Hash.send(:include, OpenHash)
@@ -0,0 +1,57 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{pipeline_toolkit}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Aisha Fenton"]
9
+ s.date = %q{2009-09-23}
10
+ s.email = %q{labs@visfleet.com}
11
+ s.executables = ["msg_probe.rb", "msg_subscribe.rb", "msg_push.rb", "msg_pop.rb", "msg_sink.rb"]
12
+ s.extra_rdoc_files = [
13
+ "LICENSE",
14
+ "README.rdoc"
15
+ ]
16
+ s.files = [
17
+ ".document",
18
+ ".gitignore",
19
+ "LICENSE",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "bin/msg_pop.rb",
24
+ "bin/msg_probe.rb",
25
+ "bin/msg_push.rb",
26
+ "bin/msg_sink.rb",
27
+ "bin/msg_subscribe.rb",
28
+ "lib/pipeline_toolkit.rb",
29
+ "lib/pipeline_toolkit/message_coder.rb",
30
+ "lib/pipeline_toolkit/message_command.rb",
31
+ "lib/pipeline_toolkit/message_popper.rb",
32
+ "lib/pipeline_toolkit/message_probe.rb",
33
+ "lib/pipeline_toolkit/message_pusher.rb",
34
+ "lib/pipeline_toolkit/message_sink.rb",
35
+ "lib/pipeline_toolkit/message_subscriber.rb",
36
+ "lib/pipeline_toolkit/open_hash.rb",
37
+ "perf_test/test_pop.rb",
38
+ "perf_test/test_pop_async.rb",
39
+ "perf_test/test_push.rb",
40
+ "pipeline_toolkit.gemspec"
41
+ ]
42
+ s.homepage = %q{http://github.com/visfleet/pipeline_toolkit}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.5}
46
+ s.summary = %q{Toolkit for building processing pipelines using Unix Pipes and AMQP messages}
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ else
54
+ end
55
+ else
56
+ end
57
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visfleet-pipeline_toolkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aisha Fenton
@@ -9,17 +9,18 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-09 00:00:00 -07:00
12
+ date: 2009-09-23 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
16
  description:
17
17
  email: labs@visfleet.com
18
18
  executables:
19
- - monitor.rb
20
- - subscribe.rb
21
- - push.rb
22
- - pop.rb
19
+ - msg_probe.rb
20
+ - msg_subscribe.rb
21
+ - msg_push.rb
22
+ - msg_pop.rb
23
+ - msg_sink.rb
23
24
  extensions: []
24
25
 
25
26
  extra_rdoc_files:
@@ -31,9 +32,25 @@ files:
31
32
  - LICENSE
32
33
  - README.rdoc
33
34
  - Rakefile
35
+ - VERSION
36
+ - bin/msg_pop.rb
37
+ - bin/msg_probe.rb
38
+ - bin/msg_push.rb
39
+ - bin/msg_sink.rb
40
+ - bin/msg_subscribe.rb
41
+ - lib/pipeline_toolkit.rb
42
+ - lib/pipeline_toolkit/message_coder.rb
43
+ - lib/pipeline_toolkit/message_command.rb
44
+ - lib/pipeline_toolkit/message_popper.rb
45
+ - lib/pipeline_toolkit/message_probe.rb
46
+ - lib/pipeline_toolkit/message_pusher.rb
47
+ - lib/pipeline_toolkit/message_sink.rb
48
+ - lib/pipeline_toolkit/message_subscriber.rb
49
+ - lib/pipeline_toolkit/open_hash.rb
34
50
  - perf_test/test_pop.rb
35
51
  - perf_test/test_pop_async.rb
36
52
  - perf_test/test_push.rb
53
+ - pipeline_toolkit.gemspec
37
54
  has_rdoc: false
38
55
  homepage: http://github.com/visfleet/pipeline_toolkit
39
56
  licenses:
data/bin/push.rb DELETED
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'trollop'
5
- require 'pipeline_toolkit'
6
-
7
- opts = Trollop::options do
8
- opt :destinations, "Destinations", :short => "d", :type => :strings
9
- opt :route_eval, "A string of ruby code that ", :short => "e", :type => :string
10
- opt :route_file, "A string of ruby code that ", :short => "f", :type => :string
11
-
12
- # Msg server
13
- opt :host, "The AMQP message server host", :default => "localhost"
14
- opt :port, "The AMQP message server port", :default => "5672"
15
- opt :user, "The AMQP message server username", :default => "guest"
16
- opt :pass, "The AMQP message server username", :default => "guest"
17
- opt :vhost, "The AMQP message server vhost", :default => "/"
18
- end
19
-
20
- MessagePusher.new(opts).start
21
-
22
- # pop -s raw | thingie | push -d my_queue
23
- # pop -s raw | thingie | push -f "(msg.tmu_id.hash % NUMBER_OF_FORKS).to_s"
24
- # pop -s raw | thingie | push -f "Socket.gethostname"
25
- # pop -s raw | thingie | push -f "require route_to_site"