pipeline_toolkit 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +21 -5
- data/Rakefile +4 -2
- data/VERSION +1 -1
- data/bin/msg_generator.rb +0 -36
- data/bin/msg_probe.rb +4 -2
- data/bin/msg_subscribe.rb +8 -2
- data/lib/pipeline_toolkit.rb +1 -0
- data/lib/pipeline_toolkit/default_logger.rb +2 -4
- data/lib/pipeline_toolkit/message_command.rb +9 -2
- data/lib/pipeline_toolkit/message_probe.rb +10 -3
- data/lib/pipeline_toolkit/message_pusher.rb +10 -3
- data/lib/pipeline_toolkit/message_subscriber.rb +129 -19
- data/lib/pipeline_toolkit/socket_util.rb +24 -0
- data/pipeline_toolkit.gemspec +15 -8
- metadata +25 -4
data/README.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Pipeline Toolkit
|
2
2
|
by VisFleet
|
3
3
|
|
4
|
-
Command line tools for processing messages by constructing a pipeline of workers. AMQP and Unix pipes are used to construct the pipeline. Messages are simple
|
4
|
+
Command line tools for processing messages by constructing a pipeline of workers. AMQP and Unix pipes are used to construct the pipeline. Messages are simple Hashes (serialized as YAML) so they can hold any values and change throughout the processing.
|
5
5
|
|
6
6
|
Provides:
|
7
7
|
- Processing acknowledgments, ensuring the a message is only disposed of once it has been successful processed
|
@@ -14,8 +14,7 @@ Provides:
|
|
14
14
|
|
15
15
|
== Install
|
16
16
|
|
17
|
-
> gem
|
18
|
-
> sudo gem install visfleet-pipeline_toolkit
|
17
|
+
> sudo gem install pipeline_toolkit
|
19
18
|
|
20
19
|
=== Dependancies
|
21
20
|
|
@@ -37,7 +36,7 @@ It is assumed that you have:
|
|
37
36
|
end
|
38
37
|
MyWorker.new.start
|
39
38
|
|
40
|
-
2. Hook it up to
|
39
|
+
2. Hook it up to a AMQP message source
|
41
40
|
|
42
41
|
> msg_subscribe.rb -q source | my_worker.rb | msg_push.rb -x dest
|
43
42
|
|
@@ -48,7 +47,24 @@ You can learn more about the command line tools and what options are available b
|
|
48
47
|
> msg_sink --help
|
49
48
|
> msg_probe --help
|
50
49
|
|
50
|
+
== Examples
|
51
51
|
|
52
|
-
|
52
|
+
Generate a bunch of sample messages and push them to an AMQP exchange 'test-exchange'. Hook up a pipe to consume and push results to /dev/null. Goto http://localhost:9090 to see message throughput.
|
53
|
+
|
54
|
+
> msg_generator.rb | msg_push.rb -x test-exchange
|
55
|
+
> msg_subscribe.rb --http-port 9090 -x test-exchange -q test_queue > /dev/null
|
56
|
+
|
57
|
+
Same as above, but this time with acknowledgements switched on. This guarantees that a message isn't removed from the message server until handled. msg_sink.rb acknowledges all messages.
|
58
|
+
|
59
|
+
> msg_generator.rb | msg_push.rb -x test-exchange
|
60
|
+
> msg_subscribe.rb -a -x test-exchange -q test_queue | msg_sink.rb
|
61
|
+
|
62
|
+
== Todo
|
63
|
+
|
64
|
+
- Logging. For the moment we're using SysLogLogger (which requires Syslog). This needs to be switched to the default ruby logging, and we need to find out a way to plug in alternatives if required.
|
65
|
+
|
66
|
+
- DNS-SD is broken. See http://github.com/tenderlove/dnssd/issues#issue/3
|
67
|
+
|
68
|
+
- Decide if we want to support other exchange, queue and binding configurations. For example, exchanges are always fanout and durable at the moment.
|
53
69
|
|
54
70
|
|
data/Rakefile
CHANGED
@@ -10,9 +10,11 @@ begin
|
|
10
10
|
gem.homepage = "http://github.com/visfleet/pipeline_toolkit"
|
11
11
|
gem.authors = ["Aisha Fenton"]
|
12
12
|
gem.executables = ["msg_probe.rb", "msg_subscribe.rb", "msg_push.rb", "msg_sink.rb", "msg_generator.rb"]
|
13
|
-
gem.add_runtime_dependency('amqp', ">=0.6.
|
13
|
+
gem.add_runtime_dependency('amqp', ">=0.6.5")
|
14
14
|
gem.add_runtime_dependency('trollop', ">=1.14")
|
15
|
-
gem.add_runtime_dependency('eventmachine', ">=0.12.
|
15
|
+
gem.add_runtime_dependency('eventmachine', ">=0.12.10")
|
16
|
+
gem.add_runtime_dependency('eventmachine_httpserver', ">=0.2.0")
|
17
|
+
gem.add_runtime_dependency('SyslogLogger', ">=1.4.0")
|
16
18
|
end
|
17
19
|
Jeweler::GemcutterTasks.new
|
18
20
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/bin/msg_generator.rb
CHANGED
@@ -1,36 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'trollop'
|
4
|
-
require 'pipeline_toolkit'
|
5
|
-
|
6
|
-
opts = Trollop::options do
|
7
|
-
banner <<-EOS
|
8
|
-
Generates messages for testing the pipeline
|
9
|
-
Usage:
|
10
|
-
msg_generator.rb -m "My message"
|
11
|
-
EOS
|
12
|
-
opt :msg, "The message to send", :short => "m", :default => "Test message"
|
13
|
-
opt :delay, "Sleep time between sends in seconds", :short => "d", :type => :float
|
14
|
-
end
|
15
|
-
|
16
|
-
class MsgGenerator
|
17
|
-
|
18
|
-
def initialize(opts)
|
19
|
-
@delay = opts.delay
|
20
|
-
@msg = opts.msg
|
21
|
-
end
|
22
|
-
|
23
|
-
def start
|
24
|
-
loop do
|
25
|
-
self.send_msg(@msg)
|
26
|
-
sleep(@delay) unless @delay.nil?
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def send_msg(msg)
|
31
|
-
puts MessageCoder.encode(@msg)
|
32
|
-
$stdout.flush
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
MsgGenerator.new(opts).start
|
data/bin/msg_probe.rb
CHANGED
@@ -6,8 +6,10 @@ require 'pipeline_toolkit'
|
|
6
6
|
|
7
7
|
opts = Trollop::options do
|
8
8
|
opt :interval, "Time in seconds between updates", :short => "i", :default => 2
|
9
|
-
opt :http_port, "The HTTP server
|
9
|
+
opt :http_port, "The port the HTTP server runs on. Default is a random port between 10000-11000", :type => :integer
|
10
10
|
opt :name, "The name of the probe. Used in monitoring", :type => :string, :short => 'n'
|
11
|
+
opt :dnssd, "Switches on DNSSD (i.e. Bonjour) for the monitoring interface", :short => 'd'
|
11
12
|
end
|
12
13
|
|
13
|
-
MessageProbe.new(opts).start
|
14
|
+
MessageProbe.new(opts).start
|
15
|
+
|
data/bin/msg_subscribe.rb
CHANGED
@@ -4,11 +4,17 @@ require 'trollop'
|
|
4
4
|
require 'pipeline_toolkit'
|
5
5
|
|
6
6
|
opts = Trollop::options do
|
7
|
-
|
8
|
-
opt :
|
7
|
+
# Monitoring
|
8
|
+
opt :name, "The name used to describe the entire process chain", :short => "n", :type => :string
|
9
|
+
opt :http_port, "The port the HTTP monitoring server runs on. Default is a random port between 10000-11000", :type => :integer
|
10
|
+
opt :dnssd, "Switches on DNSSD (i.e. Bonjour) for the monitoring interface", :short => 'd'
|
11
|
+
|
12
|
+
# Messages
|
13
|
+
opt :queue, "The source queue", :short => "q", :type => :string, :required => true
|
9
14
|
opt :ack, "Switch that requires that messages are successfully processed before continuing with the next message", :short => "a"
|
10
15
|
opt :topic, "The queue topic to subscribe to", :short => "t", :type => :string
|
11
16
|
opt :max_unackd, "The maximum number of unaknowledged messages to buffer before waiting for them to be acknowledged. Defaults to 100", :default => 100
|
17
|
+
opt :exchange_bind, "Binds the the queue to the specified exchange. The created exchange is (for now) fanout, durable, and not passive", :short => "x", :type => :string
|
12
18
|
|
13
19
|
# Msg server
|
14
20
|
opt :host, "The AMQP message server host", :default => "localhost"
|
data/lib/pipeline_toolkit.rb
CHANGED
@@ -16,9 +16,9 @@ module MessageCommand
|
|
16
16
|
|
17
17
|
begin
|
18
18
|
EM.run do
|
19
|
-
self.init_loop
|
20
19
|
conn = EM.watch($stdin, ProcessLine, self)
|
21
20
|
conn.notify_readable = true
|
21
|
+
self.init_loop
|
22
22
|
end
|
23
23
|
rescue StandardError => e
|
24
24
|
log.info e
|
@@ -53,7 +53,8 @@ module MessageCommand
|
|
53
53
|
|
54
54
|
def ack_msg(msg)
|
55
55
|
return unless @use_ack
|
56
|
-
|
56
|
+
msg = {:msg_type => :ack, :ack_id => msg.ack_id}
|
57
|
+
@sys_pipe.syswrite(MessageCoder.encode(msg) << "\n")
|
57
58
|
end
|
58
59
|
|
59
60
|
def pass_on_msg(msg)
|
@@ -66,6 +67,11 @@ module MessageCommand
|
|
66
67
|
# Implemented in class that includes me
|
67
68
|
end
|
68
69
|
|
70
|
+
# Can be overriden in included class. Called when the sys_pipe has been established.
|
71
|
+
def syspipe_open
|
72
|
+
# Implemented in class that includes me
|
73
|
+
end
|
74
|
+
|
69
75
|
# Override in included class. Processes a message. This method
|
70
76
|
# must return either a msg object -- which may or may not have been modified -- or the symbol :ack.
|
71
77
|
# Returning :ack mean that the message has been dealt with and can be acknowledged back to the queue
|
@@ -80,6 +86,7 @@ module MessageCommand
|
|
80
86
|
@use_ack = msg.use_ack
|
81
87
|
@max_unackd = msg.max_unackd
|
82
88
|
msg
|
89
|
+
self.syspipe_open
|
83
90
|
end
|
84
91
|
|
85
92
|
module ProcessLine
|
@@ -6,10 +6,11 @@ class MessageProbe
|
|
6
6
|
|
7
7
|
def initialize(opts)
|
8
8
|
@interval = opts.interval
|
9
|
-
@http_port= opts.http_port
|
9
|
+
@http_port= opts.http_port || Socket.select_random_port(10_000, 11_000)
|
10
10
|
@start_time = Time.now
|
11
11
|
@name = opts.name
|
12
12
|
self.reset
|
13
|
+
self.init_dnssd if opts.dnssd
|
13
14
|
end
|
14
15
|
|
15
16
|
def init_loop
|
@@ -17,10 +18,14 @@ class MessageProbe
|
|
17
18
|
EM.add_periodic_timer(@interval) { self.tick }
|
18
19
|
end
|
19
20
|
|
21
|
+
def init_dnssd
|
22
|
+
require 'dnssd'
|
23
|
+
DNSSD.register!("#{@name} probe", "_http._tcp", nil, @http_port)
|
24
|
+
end
|
25
|
+
|
20
26
|
def tick
|
21
27
|
@time_delta = Time.now - @prev_time
|
22
28
|
@mps = @count / @time_delta
|
23
|
-
|
24
29
|
self.reset
|
25
30
|
end
|
26
31
|
|
@@ -33,6 +38,8 @@ class MessageProbe
|
|
33
38
|
Time.now - @start_time
|
34
39
|
end
|
35
40
|
|
41
|
+
# OPTIMIZE. can improve performance by overriding base process_line method
|
42
|
+
# saving us the unnecessary marshal step.
|
36
43
|
def process_message(msg)
|
37
44
|
@count += 1
|
38
45
|
msg
|
@@ -94,7 +101,7 @@ class ProbeHttpRequest < EM::Connection
|
|
94
101
|
<td>messages per second:</td><td><span class="mps">#{@probe.mps}</span></td><td></td>
|
95
102
|
</tr>
|
96
103
|
<tr>
|
97
|
-
<td>uptime:</td><td><span class="uptime">#{@probe.uptime.to_i / 60}</span></td><td>mins</td
|
104
|
+
<td>uptime:</td><td><span class="uptime">#{@probe.uptime.to_i / 60}</span></td><td>mins</td>
|
98
105
|
</tr>
|
99
106
|
</table>
|
100
107
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "mq"
|
2
2
|
|
3
|
-
class MessagePusher
|
3
|
+
class MessagePusher
|
4
4
|
include MessageCommand
|
5
5
|
|
6
6
|
def initialize(opts)
|
@@ -27,6 +27,12 @@ class MessagePusher
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def syspipe_open
|
31
|
+
# Send back details of where messages are going
|
32
|
+
msg = {:msg_type => :pipe_desc, :exchanges => @exchange_names.join(",")}
|
33
|
+
self.sys_pipe.syswrite(MessageCoder.encode(msg) << "\n")
|
34
|
+
end
|
35
|
+
|
30
36
|
def load_route(key_file)
|
31
37
|
require key_file
|
32
38
|
self.extend eval(classify(key_file.gsub(".rb", "")))
|
@@ -45,8 +51,9 @@ class MessagePusher
|
|
45
51
|
def process_message(msg)
|
46
52
|
@exchanges.each do |exchange|
|
47
53
|
key = route_key(msg)
|
48
|
-
exchange.publish(msg.to_yaml
|
49
|
-
# OPTIMIZE. Using MessageCoder.encode(msg) instead of to_yaml is 2x faster. But won't be easy to
|
54
|
+
exchange.publish(msg.to_yaml)
|
55
|
+
# OPTIMIZE. Using MessageCoder.encode(msg) instead of to_yaml is 2x faster. But won't be easy to
|
56
|
+
# debug. Worth it?
|
50
57
|
end
|
51
58
|
:ack
|
52
59
|
end
|
@@ -5,47 +5,76 @@ require "socket"
|
|
5
5
|
|
6
6
|
class MessageSubscriber
|
7
7
|
include DefaultLogger
|
8
|
-
|
8
|
+
|
9
|
+
attr_reader :name, :start_time, :mps, :queue_name
|
10
|
+
attr_accessor :exchanges_out
|
11
|
+
|
9
12
|
PIPE_PATH = "/tmp"
|
10
13
|
|
11
14
|
def initialize(opts)
|
12
|
-
@exchange_name, @exchange_type = opts[:
|
15
|
+
@exchange_name, @exchange_type = opts[:exchange_bind].split(":")
|
13
16
|
@queue_name = opts[:queue]
|
14
17
|
@use_ack = opts[:ack]
|
15
18
|
@topic = opts[:topic]
|
16
19
|
@msg_server_opts = opts.select_keys(:host, :port, :user, :pass, :vhost)
|
17
20
|
@unackd_msgs = {}
|
18
21
|
@max_unackd = opts[:max_unackd]
|
22
|
+
|
23
|
+
@http_port = opts.http_port || Socket.select_random_port(10_000, 11_000)
|
24
|
+
@name = opts.name || (Socket.gethostname + '_' + Process.pid.to_s)
|
25
|
+
self.init_dnssd if opts.dnssd
|
26
|
+
self.reset
|
27
|
+
end
|
28
|
+
|
29
|
+
def init_dnssd
|
30
|
+
# FIXME. DNS-SD breaks when under load. Not sure what problem is yet, have raised it with
|
31
|
+
# gem author:
|
32
|
+
# http://github.com/tenderlove/dnssd/issues#issue/3
|
33
|
+
require 'dnssd'
|
34
|
+
DNSSD.register!("#{@name}_pipe", "_http._tcp", nil, @http_port)
|
19
35
|
end
|
20
36
|
|
21
37
|
def start
|
22
|
-
|
23
|
-
Signal.trap('
|
38
|
+
# FIXME. Need to do more investigation on if/when messages are lost with shutdowns
|
39
|
+
Signal.trap('INT') { AMQP.stop{ EM.stop } }
|
40
|
+
Signal.trap('TERM') { AMQP.stop{ EM.stop } }
|
24
41
|
|
25
42
|
begin
|
26
43
|
self.create_sys_pipe
|
27
44
|
AMQP.start(@msg_server_opts) do
|
28
|
-
|
29
|
-
# otherwise all items in your queue will be returned
|
30
|
-
# FIXME. Doesn't shut down cleanly with these commands included. Why?
|
31
|
-
|
45
|
+
@start_time = Time.now
|
32
46
|
self.setup_queue
|
33
47
|
# NB. prefetch limits the amount of unknowledged messages that come down the pipe.
|
34
48
|
MQ.prefetch(@max_unackd)
|
35
49
|
@queue.subscribe(:ack => @use_ack) do |header, body|
|
36
|
-
|
50
|
+
self.process_message(header, body)
|
37
51
|
end
|
38
52
|
|
39
|
-
EM.
|
53
|
+
conn = EM.watch(@sys_pipe, HandleCtlMessages, @sys_pipe, self)
|
54
|
+
conn.notify_readable = true
|
55
|
+
|
56
|
+
EM.start_server('0.0.0.0', @http_port, PipeHttpRequest, self)
|
57
|
+
EM.add_periodic_timer(5) { self.calc_stats }
|
40
58
|
end
|
41
59
|
rescue StandardError => e
|
42
|
-
log.
|
60
|
+
log.error e.message + " " + e.backtrace.join("\n")
|
43
61
|
raise e
|
44
62
|
ensure
|
45
63
|
self.shutdown
|
46
64
|
end
|
47
65
|
end
|
48
66
|
|
67
|
+
def calc_stats
|
68
|
+
@time_delta = Time.now - @prev_time
|
69
|
+
@mps = @count / @time_delta
|
70
|
+
self.reset
|
71
|
+
end
|
72
|
+
|
73
|
+
def reset
|
74
|
+
@count = 0
|
75
|
+
@prev_time = Time.now
|
76
|
+
end
|
77
|
+
|
49
78
|
def shutdown
|
50
79
|
log.info "Shutting down"
|
51
80
|
self.destroy_sys_pipe
|
@@ -63,7 +92,7 @@ class MessageSubscriber
|
|
63
92
|
end
|
64
93
|
|
65
94
|
def create_exchange(name, type)
|
66
|
-
MQ::Exchange.new(MQ.default, type.to_sym, @exchange_name, :durable => true, :passive => false)
|
95
|
+
MQ::Exchange.new(MQ.default, type.to_sym, @exchange_name, :durable => true, :passive => false)
|
67
96
|
end
|
68
97
|
|
69
98
|
def create_sys_pipe
|
@@ -103,34 +132,115 @@ class MessageSubscriber
|
|
103
132
|
"#{@seed}#{@ix += 1}"
|
104
133
|
end
|
105
134
|
|
106
|
-
def
|
135
|
+
def process_message(header, body)
|
107
136
|
msg = YAML.load(body)
|
108
137
|
store_ack(msg, header) if @use_ack
|
109
138
|
write_msg(msg)
|
110
139
|
end
|
111
140
|
|
112
141
|
def write_msg(msg)
|
142
|
+
@count += 1
|
113
143
|
$stdout.syswrite(MessageCoder.encode(msg) << "\n")
|
114
144
|
end
|
115
145
|
|
146
|
+
def perform_ack(ack_id)
|
147
|
+
header = @unackd_msgs.delete(ack_id)
|
148
|
+
header.ack
|
149
|
+
end
|
150
|
+
|
116
151
|
def store_ack(msg, header)
|
117
152
|
msg.ack_id = header.delivery_tag.to_s
|
118
153
|
@unackd_msgs[msg.ack_id] = header
|
119
154
|
end
|
120
155
|
|
121
156
|
# Handles msg acks
|
122
|
-
module
|
157
|
+
module HandleCtlMessages
|
123
158
|
include DefaultLogger
|
124
159
|
|
125
|
-
def initialize(sys_pipe,
|
160
|
+
def initialize(sys_pipe, msg_sub)
|
126
161
|
@sys_pipe = sys_pipe
|
127
|
-
@
|
162
|
+
@msg_sub = msg_sub
|
128
163
|
end
|
129
164
|
|
130
165
|
def notify_readable
|
131
|
-
|
132
|
-
|
133
|
-
|
166
|
+
msg = MessageCoder.decode(@sys_pipe.gets.chomp!)
|
167
|
+
case msg[:msg_type]
|
168
|
+
when :ack
|
169
|
+
@msg_sub.perform_ack(msg.ack_id)
|
170
|
+
when :pipe_desc
|
171
|
+
@msg_sub.exchanges_out = msg.exchanges
|
172
|
+
else
|
173
|
+
raise Exception.new("Unknown control message received: #{message}")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class PipeHttpRequest < EM::Connection
|
179
|
+
include EM::HttpServer
|
180
|
+
|
181
|
+
def initialize(msg_sub)
|
182
|
+
@msg_sub = msg_sub
|
183
|
+
end
|
184
|
+
|
185
|
+
def post_init
|
186
|
+
super
|
187
|
+
no_environment_strings
|
188
|
+
end
|
189
|
+
|
190
|
+
def process_http_request
|
191
|
+
response = EM::DelegatedHttpResponse.new(self)
|
192
|
+
response.status = 200
|
193
|
+
response.content_type 'text/html'
|
194
|
+
response.content = <<-EOL
|
195
|
+
<html>
|
196
|
+
<head>
|
197
|
+
<title>Message Probe</title>
|
198
|
+
<style type="text/css">
|
199
|
+
body {
|
200
|
+
background: black;
|
201
|
+
color: #80c0c0;
|
202
|
+
}
|
203
|
+
h1 {
|
204
|
+
font: 12pt Monospace;
|
205
|
+
text-align:center;
|
206
|
+
}
|
207
|
+
table {
|
208
|
+
font: 10pt Monospace;
|
209
|
+
margin-left:auto;
|
210
|
+
margin-right:auto;
|
211
|
+
text-align:right;
|
212
|
+
}
|
213
|
+
.page {
|
214
|
+
position:relative;
|
215
|
+
top: 20%;
|
216
|
+
# border-style:solid;
|
217
|
+
# border-width:5px;
|
218
|
+
width: 30%;
|
219
|
+
margin-left:auto;
|
220
|
+
margin-right:auto;
|
221
|
+
}
|
222
|
+
</style>
|
223
|
+
</head>
|
224
|
+
<body>
|
225
|
+
<div class=page>
|
226
|
+
<h1><span class="name">#{@msg_sub.name}</span></h1>
|
227
|
+
<table>
|
228
|
+
<tr>
|
229
|
+
<td>Structure:</td><td><span class="queue_in">#{@msg_sub.queue_name}</span> -> <span class="exchanges_out">#{@msg_sub.exchanges_out}</span></td>
|
230
|
+
</tr>
|
231
|
+
<tr>
|
232
|
+
<td>Throughput:</td><td><span class="mps">#{@msg_sub.mps.to_i}</span></td>
|
233
|
+
</tr>
|
234
|
+
<tr>
|
235
|
+
<td>Uptime:</td><td><span class="uptime">#{(Time.now - @msg_sub.start_time).to_i / 60}mins</span></td>
|
236
|
+
</tr>
|
237
|
+
</table>
|
238
|
+
</div>
|
239
|
+
</body>
|
240
|
+
</html>
|
241
|
+
EOL
|
242
|
+
|
243
|
+
response.send_response
|
134
244
|
end
|
135
245
|
end
|
136
246
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
# Extend socket class
|
3
|
+
class Socket
|
4
|
+
|
5
|
+
def self.select_random_port(low, high, host = "localhost")
|
6
|
+
raise Exception.new("'low' must be lower than 'high'") unless low < high
|
7
|
+
port = nil
|
8
|
+
begin
|
9
|
+
port = low + rand(high - low)
|
10
|
+
end while Socket.socket_in_use?(host, port)
|
11
|
+
port
|
12
|
+
end
|
13
|
+
|
14
|
+
# OPTIMIZE. Is there a better way to do this? Feels ugly to me.
|
15
|
+
def self.socket_in_use?(host, port)
|
16
|
+
begin
|
17
|
+
TCPSocket.new(host, port)
|
18
|
+
rescue Errno::ECONNREFUSED => e
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
return true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/pipeline_toolkit.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{pipeline_toolkit}
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aisha Fenton"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-01-15}
|
13
13
|
s.email = %q{labs@visfleet.com}
|
14
14
|
s.executables = ["msg_probe.rb", "msg_subscribe.rb", "msg_push.rb", "msg_sink.rb", "msg_generator.rb"]
|
15
15
|
s.extra_rdoc_files = [
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
"lib/pipeline_toolkit/message_sink.rb",
|
35
35
|
"lib/pipeline_toolkit/message_subscriber.rb",
|
36
36
|
"lib/pipeline_toolkit/open_hash.rb",
|
37
|
+
"lib/pipeline_toolkit/socket_util.rb",
|
37
38
|
"monitor/munin.rb",
|
38
39
|
"pipeline_toolkit.gemspec"
|
39
40
|
]
|
@@ -48,18 +49,24 @@ Gem::Specification.new do |s|
|
|
48
49
|
s.specification_version = 3
|
49
50
|
|
50
51
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
-
s.add_runtime_dependency(%q<amqp>, [">= 0.6.
|
52
|
+
s.add_runtime_dependency(%q<amqp>, [">= 0.6.5"])
|
52
53
|
s.add_runtime_dependency(%q<trollop>, [">= 1.14"])
|
53
|
-
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.
|
54
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
|
55
|
+
s.add_runtime_dependency(%q<eventmachine_httpserver>, [">= 0.2.0"])
|
56
|
+
s.add_runtime_dependency(%q<SyslogLogger>, [">= 1.4.0"])
|
54
57
|
else
|
55
|
-
s.add_dependency(%q<amqp>, [">= 0.6.
|
58
|
+
s.add_dependency(%q<amqp>, [">= 0.6.5"])
|
56
59
|
s.add_dependency(%q<trollop>, [">= 1.14"])
|
57
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.
|
60
|
+
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
61
|
+
s.add_dependency(%q<eventmachine_httpserver>, [">= 0.2.0"])
|
62
|
+
s.add_dependency(%q<SyslogLogger>, [">= 1.4.0"])
|
58
63
|
end
|
59
64
|
else
|
60
|
-
s.add_dependency(%q<amqp>, [">= 0.6.
|
65
|
+
s.add_dependency(%q<amqp>, [">= 0.6.5"])
|
61
66
|
s.add_dependency(%q<trollop>, [">= 1.14"])
|
62
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.
|
67
|
+
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
68
|
+
s.add_dependency(%q<eventmachine_httpserver>, [">= 0.2.0"])
|
69
|
+
s.add_dependency(%q<SyslogLogger>, [">= 1.4.0"])
|
63
70
|
end
|
64
71
|
end
|
65
72
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pipeline_toolkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aisha Fenton
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-15 00:00:00 +13:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.6.
|
23
|
+
version: 0.6.5
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: trollop
|
@@ -40,7 +40,27 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.12.
|
43
|
+
version: 0.12.10
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: eventmachine_httpserver
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.2.0
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: SyslogLogger
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.4.0
|
44
64
|
version:
|
45
65
|
description:
|
46
66
|
email: labs@visfleet.com
|
@@ -73,6 +93,7 @@ files:
|
|
73
93
|
- lib/pipeline_toolkit/message_sink.rb
|
74
94
|
- lib/pipeline_toolkit/message_subscriber.rb
|
75
95
|
- lib/pipeline_toolkit/open_hash.rb
|
96
|
+
- lib/pipeline_toolkit/socket_util.rb
|
76
97
|
- monitor/munin.rb
|
77
98
|
- pipeline_toolkit.gemspec
|
78
99
|
has_rdoc: true
|