scout-gear 8.1.0 → 9.0.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.
- checksums.yaml +4 -4
- data/.vimproject +22 -0
- data/VERSION +1 -1
- data/bin/scout +1 -0
- data/lib/rbbt-scout.rb +2 -1
- data/lib/scout/cmd.rb +9 -5
- data/lib/scout/indiferent_hash.rb +17 -0
- data/lib/scout/log/progress/report.rb +1 -0
- data/lib/scout/log.rb +14 -11
- data/lib/scout/misc/filesystem.rb +2 -3
- data/lib/scout/offsite/ssh.rb +3 -0
- data/lib/scout/offsite/step.rb +20 -3
- data/lib/scout/open/stream.rb +0 -1
- data/lib/scout/open.rb +8 -8
- data/lib/scout/path.rb +1 -1
- data/lib/scout/persist/serialize.rb +1 -1
- data/lib/scout/resource/open.rb +8 -0
- data/lib/scout/resource/path.rb +12 -9
- data/lib/scout/resource/software.rb +4 -2
- data/lib/scout/resource.rb +2 -0
- data/lib/scout/tsv/dumper.rb +3 -1
- data/lib/scout/tsv/parser.rb +13 -3
- data/lib/scout/work_queue.rb +1 -0
- data/lib/scout/workflow/deployment/orchestrator.rb +17 -8
- data/lib/scout/workflow/step/dependencies.rb +9 -3
- data/lib/scout/workflow/step/info.rb +8 -0
- data/lib/scout/workflow/step/inputs.rb +5 -0
- data/lib/scout/workflow/step/status.rb +22 -2
- data/lib/scout/workflow/step.rb +11 -4
- data/lib/scout/workflow/task/dependencies.rb +2 -0
- data/lib/scout/workflow/task/inputs.rb +14 -9
- data/lib/scout/workflow/task.rb +4 -2
- data/lib/scout/workflow/usage.rb +21 -33
- data/lib/scout/workflow.rb +17 -13
- data/scout-gear.gemspec +9 -3
- data/scout_commands/resource/produce +66 -0
- data/scout_commands/template +52 -0
- data/scout_commands/workflow/install +3 -0
- data/scout_commands/workflow/task +24 -5
- data/share/software/install_helpers +2 -2
- data/share/templates/command +25 -0
- data/share/templates/workflow.rb +14 -0
- data/test/scout/offsite/test_step.rb +0 -1
- data/test/scout/test_persist.rb +2 -2
- data/test/scout/test_work_queue.rb +1 -1
- data/test/scout/tsv/test_parser.rb +21 -0
- data/test/scout/workflow/step/test_info.rb +0 -1
- data/test/scout/workflow/task/test_dependencies.rb +2 -0
- data/test/scout/workflow/task/test_inputs.rb +0 -1
- data/test/scout/workflow/test_definition.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98b3f84350f2f451b717f004bfc97cd7767f7e0fed58e1a2d0cd023bc700185f
|
4
|
+
data.tar.gz: '00847ad4d92b1cab22305ea867dc12c870b22e192e79536917f82aa90cc82989'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4af5e13873fa13dea33161e9200aa725bb4329899e9242ae6504ffae2ab82e7eb01b82a53edc2a4331ede06d0f12bb07f86f579cb29ecbf0d36e791bf6d53f3e
|
7
|
+
data.tar.gz: fc773eb933e5c851aa1d642e872df02d282fbcb29ee1b8e1bf150ffebf9bd4ce8c3670d43a284ff2c8197477a8cf6f71dfcd49b265ad938c723292ec57579998
|
data/.vimproject
CHANGED
@@ -10,6 +10,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
10
10
|
glob
|
11
11
|
doc
|
12
12
|
update
|
13
|
+
template
|
13
14
|
offsite
|
14
15
|
workflow=workflow{
|
15
16
|
task
|
@@ -17,6 +18,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
17
18
|
info
|
18
19
|
install
|
19
20
|
}
|
21
|
+
resource=resource{
|
22
|
+
produce
|
23
|
+
}
|
20
24
|
}
|
21
25
|
lib=lib {
|
22
26
|
scout-gear.rb
|
@@ -115,6 +119,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
115
119
|
progress.rb
|
116
120
|
provenance.rb
|
117
121
|
status.rb
|
122
|
+
inputs.rb
|
118
123
|
}
|
119
124
|
task.rb
|
120
125
|
task=task{
|
@@ -168,6 +173,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
168
173
|
sync.rb
|
169
174
|
step.rb
|
170
175
|
}
|
176
|
+
hpc=hpc{
|
177
|
+
slurm.rb
|
178
|
+
}
|
171
179
|
}
|
172
180
|
}
|
173
181
|
test=test {
|
@@ -198,7 +206,18 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
198
206
|
test_task.rb
|
199
207
|
test_usage.rb
|
200
208
|
test_util.rb
|
209
|
+
step=step{
|
210
|
+
test_dependencies.rb
|
211
|
+
test_info.rb
|
212
|
+
test_load.rb
|
213
|
+
test_provenance.rb
|
214
|
+
test_status.rb
|
201
215
|
}
|
216
|
+
task=task{
|
217
|
+
test_dependencies.rb
|
218
|
+
test_inputs.rb
|
219
|
+
}
|
220
|
+
}
|
202
221
|
indiferent_hash=indiferent_hash{
|
203
222
|
test_case_insensitive.rb
|
204
223
|
test_options.rb
|
@@ -209,6 +228,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
209
228
|
software=software{
|
210
229
|
install_helpers
|
211
230
|
}
|
231
|
+
templates=templates{
|
232
|
+
workflow.rb
|
233
|
+
}
|
212
234
|
}
|
213
235
|
|
214
236
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
9.0.0
|
data/bin/scout
CHANGED
data/lib/rbbt-scout.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
$LOAD_PATH.unshift File.join(__dir__, '../modules/rbbt-util/lib')
|
2
2
|
module Rbbt
|
3
3
|
extend Resource
|
4
|
-
self.pkgdir = 'rbbt'
|
5
4
|
self.path_maps = Path.path_maps.merge(:rbbt_lib => File.expand_path(File.join(__dir__, '../modules/rbbt-util/', '{TOPLEVEL}','{SUBPATH}')))
|
6
5
|
end
|
6
|
+
|
7
|
+
Resource.set_software_env Rbbt.software
|
data/lib/scout/cmd.rb
CHANGED
@@ -20,17 +20,22 @@ module CMD
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
|
23
24
|
def self.get_tool(tool)
|
24
25
|
return tool.to_s unless TOOLS[tool]
|
25
26
|
|
26
27
|
@@init_cmd_tool ||= IndiferentHash.setup({})
|
28
|
+
|
29
|
+
claim, test, block, cmd = TOOLS[tool]
|
30
|
+
cmd = tool.to_s if cmd.nil?
|
31
|
+
|
27
32
|
if !@@init_cmd_tool[tool]
|
28
|
-
|
33
|
+
|
29
34
|
begin
|
30
35
|
if test
|
31
36
|
CMD.cmd(test + " ")
|
32
37
|
else
|
33
|
-
CMD.cmd("#{
|
38
|
+
CMD.cmd("#{cmd} --help")
|
34
39
|
end
|
35
40
|
rescue
|
36
41
|
if claim
|
@@ -43,7 +48,7 @@ module CMD
|
|
43
48
|
version = nil
|
44
49
|
["--version", "-version", "--help", ""].each do |f|
|
45
50
|
begin
|
46
|
-
version_txt += CMD.cmd("#{
|
51
|
+
version_txt += CMD.cmd("#{cmd} #{f} 2>&1", :nofail => true).read
|
47
52
|
version = CMD.scan_version_text(version_txt, tool)
|
48
53
|
break if version
|
49
54
|
rescue
|
@@ -56,9 +61,8 @@ module CMD
|
|
56
61
|
return cmd if cmd
|
57
62
|
end
|
58
63
|
|
59
|
-
|
64
|
+
cmd
|
60
65
|
end
|
61
|
-
|
62
66
|
def self.scan_version_text(text, cmd = nil)
|
63
67
|
cmd = "NOCMDGIVE" if cmd.nil? || cmd.empty?
|
64
68
|
text = Misc.fixutf8 text
|
@@ -75,5 +75,22 @@ module IndiferentHash
|
|
75
75
|
end
|
76
76
|
clean
|
77
77
|
end
|
78
|
+
|
79
|
+
def slice(*list)
|
80
|
+
ext_list = []
|
81
|
+
list.each do |e|
|
82
|
+
case e
|
83
|
+
when Symbol
|
84
|
+
ext_list << e
|
85
|
+
ext_list << e.to_s
|
86
|
+
when String
|
87
|
+
ext_list << e
|
88
|
+
ext_list << e.to_sym
|
89
|
+
else
|
90
|
+
ext_list << e
|
91
|
+
end
|
92
|
+
end
|
93
|
+
IndiferentHash.setup(super(*ext_list))
|
94
|
+
end
|
78
95
|
end
|
79
96
|
|
@@ -161,6 +161,7 @@ module Log
|
|
161
161
|
def save
|
162
162
|
info = {:start => @start, :last_time => @last_time, :last_count => @last_count, :last_percent => @last_percent, :desc => @desc, :ticks => @ticks, :max => @max, :mean => @mean}
|
163
163
|
info.delete_if{|k,v| v.nil?}
|
164
|
+
FileUtils.mkdir_p File.dirname(file) unless File.exist?(File.dirname(file))
|
164
165
|
File.write(file, info.to_yaml)
|
165
166
|
end
|
166
167
|
|
data/lib/scout/log.rb
CHANGED
@@ -51,17 +51,19 @@ module Log
|
|
51
51
|
|
52
52
|
def self.tty_size
|
53
53
|
@@tty_size ||= Log.ignore_stderr do
|
54
|
-
begin
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
size = begin
|
55
|
+
IO.console.winsize.last
|
56
|
+
rescue Exception
|
57
|
+
begin
|
58
|
+
res = `tput li`
|
59
|
+
res = nil if res == ""
|
60
|
+
res || ENV["TTY_SIZE"] || 80
|
61
|
+
rescue Exception
|
62
|
+
ENV["TTY_SIZE"] || 80
|
63
|
+
end
|
64
|
+
end
|
65
|
+
size = size.to_i if String === size
|
66
|
+
size
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
@@ -269,6 +271,7 @@ module Log
|
|
269
271
|
line = line.sub('`',"'")
|
270
272
|
color = :green if line =~ /workflow/
|
271
273
|
color = :blue if line =~ /scout-/
|
274
|
+
color = :cyan if line =~ /rbbt-/
|
272
275
|
if color
|
273
276
|
Log.color color, line
|
274
277
|
else
|
@@ -16,11 +16,10 @@ module Misc
|
|
16
16
|
|
17
17
|
basedir += "/" unless basedir.slice(-2,-1) == "/"
|
18
18
|
|
19
|
-
if path.
|
20
|
-
return path
|
19
|
+
if path.start_with?(basedir)
|
20
|
+
return path.slice(basedir.length, basedir.length)
|
21
21
|
else
|
22
22
|
return nil
|
23
23
|
end
|
24
24
|
end
|
25
|
-
|
26
25
|
end
|
data/lib/scout/offsite/ssh.rb
CHANGED
@@ -21,6 +21,9 @@ class SSHLine
|
|
21
21
|
ch.exec 'bash -l'
|
22
22
|
end
|
23
23
|
|
24
|
+
@ch.send_data("[[ -f ~/.scout/environment ]] && source ~/.scout/environment\n")
|
25
|
+
@ch.send_data("[[ -f ~/.rbbt/environment ]] && source ~/.rbbt/environment\n")
|
26
|
+
|
24
27
|
@ch.on_data do |_,data|
|
25
28
|
if m = data.match(/DONECMD: (\d+)\n/)
|
26
29
|
@exit_status = m[1].to_i
|
data/lib/scout/offsite/step.rb
CHANGED
@@ -5,14 +5,14 @@ require_relative 'sync'
|
|
5
5
|
module OffsiteStep
|
6
6
|
|
7
7
|
extend MetaExtension
|
8
|
-
extension_attr :server, :workflow_name, :clean_id, :
|
8
|
+
extension_attr :server, :workflow_name, :clean_id, :slurm
|
9
9
|
|
10
10
|
def inputs_directory
|
11
11
|
@inputs_directory ||= begin
|
12
12
|
if provided_inputs && provided_inputs.any?
|
13
13
|
file = ".scout/tmp/step_inputs/#{workflow}/#{task_name}/#{name}"
|
14
14
|
TmpFile.with_path do |inputs_dir|
|
15
|
-
|
15
|
+
save_inputs(inputs_dir)
|
16
16
|
SSHLine.rsync(inputs_dir, file, target: server, directory: true)
|
17
17
|
end
|
18
18
|
file
|
@@ -68,6 +68,19 @@ job = wf.job(:#{task_name}, "#{clean_name}");
|
|
68
68
|
status == :done
|
69
69
|
end
|
70
70
|
|
71
|
+
def orchestrate_slurm
|
72
|
+
bundle_files = offsite_job_ssh <<~EOF
|
73
|
+
require 'rbbt/hpc'
|
74
|
+
HPC::BATCH_MODULE = HPC.batch_system "SLURM"
|
75
|
+
HPC::BATCH_MODULE.orchestrate_job(job, {})
|
76
|
+
job.join
|
77
|
+
job.bundle_files
|
78
|
+
EOF
|
79
|
+
SSHLine.sync(bundle_files, source: server)
|
80
|
+
self.load
|
81
|
+
end
|
82
|
+
|
83
|
+
|
71
84
|
def exec
|
72
85
|
bundle_files = offsite_job_ssh <<~EOF
|
73
86
|
job.run
|
@@ -78,6 +91,10 @@ job = wf.job(:#{task_name}, "#{clean_name}");
|
|
78
91
|
end
|
79
92
|
|
80
93
|
def run
|
81
|
-
|
94
|
+
if slurm
|
95
|
+
orchestrate_slurm
|
96
|
+
else
|
97
|
+
exec
|
98
|
+
end
|
82
99
|
end
|
83
100
|
end
|
data/lib/scout/open/stream.rb
CHANGED
@@ -66,7 +66,6 @@ module Open
|
|
66
66
|
into.close if into and into_close and not into.closed?
|
67
67
|
block.call if block_given?
|
68
68
|
|
69
|
-
Log.debug "Consume stream done #{Log.fingerprint io} -> #{Log.fingerprint(into_path ||into)}"
|
70
69
|
last_c
|
71
70
|
rescue Aborted
|
72
71
|
Thread.current["exception"] = true
|
data/lib/scout/open.rb
CHANGED
@@ -20,21 +20,21 @@ module Open
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.get_stream(file, mode = 'r')
|
23
|
+
def self.get_stream(file, mode = 'r', options = {})
|
24
24
|
return file if Open.is_stream?(file)
|
25
25
|
return file.stream if Open.has_stream?(file)
|
26
26
|
file = file.find if Path === file
|
27
27
|
|
28
|
-
return Open.ssh(file) if Open.ssh?(file)
|
29
|
-
return Open.wget(file) if Open.remote?(file)
|
28
|
+
return Open.ssh(file, options) if Open.ssh?(file)
|
29
|
+
return Open.wget(file, options) if Open.remote?(file)
|
30
30
|
|
31
31
|
File.open(file, mode)
|
32
32
|
end
|
33
33
|
|
34
|
-
def self.file_open(file, grep = false, mode = 'r', invert_grep = false)
|
34
|
+
def self.file_open(file, grep = false, mode = 'r', invert_grep = false, options = {})
|
35
35
|
Open.mkdir File.dirname(file) if mode.include? 'w'
|
36
36
|
|
37
|
-
stream = get_stream(file, mode)
|
37
|
+
stream = get_stream(file, mode, options)
|
38
38
|
|
39
39
|
if grep
|
40
40
|
grep(stream, grep, invert_grep)
|
@@ -58,7 +58,7 @@ module Open
|
|
58
58
|
def self.open(file, options = {})
|
59
59
|
if IO === file || StringIO === file
|
60
60
|
if block_given?
|
61
|
-
res = yield file
|
61
|
+
res = yield file, options
|
62
62
|
file.close
|
63
63
|
return res
|
64
64
|
else
|
@@ -72,7 +72,7 @@ module Open
|
|
72
72
|
|
73
73
|
options[:noz] = true if mode.include? "w"
|
74
74
|
|
75
|
-
io = file_open(file, options[:grep], mode, options[:invert_grep])
|
75
|
+
io = file_open(file, options[:grep], mode, options[:invert_grep], options)
|
76
76
|
|
77
77
|
io = unzip(io) if ((String === file and zip?(file)) and not options[:noz]) or options[:zip]
|
78
78
|
io = gunzip(io) if ((String === file and gzip?(file)) and not options[:noz]) or options[:gzip]
|
@@ -88,7 +88,7 @@ module Open
|
|
88
88
|
rescue DontClose
|
89
89
|
res = $!.payload
|
90
90
|
rescue Exception
|
91
|
-
io.abort if io.respond_to? :abort
|
91
|
+
io.abort $! if io.respond_to? :abort
|
92
92
|
io.join if io.respond_to? :join
|
93
93
|
raise $!
|
94
94
|
ensure
|
data/lib/scout/path.rb
CHANGED
@@ -32,7 +32,7 @@ module Path
|
|
32
32
|
prevpath = prevpath.to_s if Symbol === prevpath
|
33
33
|
|
34
34
|
subpath = File.join(prevpath.to_s, subpath) if prevpath
|
35
|
-
new = self.empty? ? subpath : File.join(self, subpath)
|
35
|
+
new = self.empty? ? subpath.dup : File.join(self, subpath)
|
36
36
|
self.annotate(new)
|
37
37
|
new
|
38
38
|
end
|
data/lib/scout/resource/path.rb
CHANGED
@@ -3,7 +3,7 @@ module Path
|
|
3
3
|
return self if ! force && (Open.exist?(self) || @produced)
|
4
4
|
begin
|
5
5
|
if Resource === self.pkgdir
|
6
|
-
self.pkgdir.produce self
|
6
|
+
self.pkgdir.produce self, force
|
7
7
|
else
|
8
8
|
false
|
9
9
|
end
|
@@ -13,7 +13,7 @@ module Path
|
|
13
13
|
message = $!.message
|
14
14
|
message = "No exception message" if message.nil? || message.empty?
|
15
15
|
Log.warn "Error producing #{self}: #{message}"
|
16
|
-
|
16
|
+
raise $!
|
17
17
|
ensure
|
18
18
|
@produced = true
|
19
19
|
end
|
@@ -33,13 +33,16 @@ module Path
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def produce_and_find(extension = nil, *args)
|
36
|
-
if extension
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
found = if extension
|
37
|
+
found = find_with_extension(extension, *args)
|
38
|
+
found.exists? ? found : produce_with_extension(extension, *args)
|
39
|
+
else
|
40
|
+
found = find
|
41
|
+
found.exists? ? found : produce(*args)
|
42
|
+
end
|
43
|
+
raise "Not found: #{self}" unless found
|
44
|
+
|
45
|
+
found
|
43
46
|
end
|
44
47
|
|
45
48
|
def relocate
|
@@ -6,7 +6,7 @@ module Resource
|
|
6
6
|
|
7
7
|
def self.install(content, name, software_dir = Path.setup('software'), &block)
|
8
8
|
software_dir ||= Path.setup('software')
|
9
|
-
software_dir = software_dir.find if Path === software_dir
|
9
|
+
software_dir = software_dir.find(:user) if Path === software_dir
|
10
10
|
|
11
11
|
content = block if block_given?
|
12
12
|
|
@@ -166,11 +166,13 @@ url='#{url}'
|
|
166
166
|
value.sub!(/^['"]/,'')
|
167
167
|
value.sub!(/['"]$/,'')
|
168
168
|
value.gsub!(/\$[a-z_0-9]+/i){|var| ENV[var[1..-1]] }
|
169
|
-
Log.debug "Set variable export from .post_install: #{
|
169
|
+
Log.debug "Set variable export from .post_install: #{Log.fingerprint [var,value]*"="}"
|
170
170
|
ENV[var] = value
|
171
171
|
end
|
172
172
|
end
|
173
173
|
end
|
174
174
|
end
|
175
175
|
end
|
176
|
+
|
177
|
+
self.set_software_env
|
176
178
|
end
|
data/lib/scout/resource.rb
CHANGED
@@ -2,7 +2,9 @@ require_relative 'log'
|
|
2
2
|
require_relative 'path'
|
3
3
|
require_relative 'resource/produce'
|
4
4
|
require_relative 'resource/path'
|
5
|
+
require_relative 'resource/open'
|
5
6
|
require_relative 'resource/util'
|
7
|
+
require_relative 'resource/software'
|
6
8
|
|
7
9
|
module Resource
|
8
10
|
extend MetaExtension
|
data/lib/scout/tsv/dumper.rb
CHANGED
@@ -11,7 +11,9 @@ module TSV
|
|
11
11
|
fields_str = "#{header_hash}#{key_field || "Id"}#{sep}#{fields*sep}"
|
12
12
|
end
|
13
13
|
|
14
|
-
if
|
14
|
+
if String === preamble
|
15
|
+
preamble_str = preamble
|
16
|
+
elsif preamble && options.values.compact.any?
|
15
17
|
preamble_str = "#: " << IndiferentHash.hash2string(options)
|
16
18
|
else
|
17
19
|
preamble_str = nil
|
data/lib/scout/tsv/parser.rb
CHANGED
@@ -51,7 +51,7 @@ module TSV
|
|
51
51
|
[key, items]
|
52
52
|
end
|
53
53
|
|
54
|
-
def self.parse_stream(stream, data: nil, source_type: nil, type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, **kargs, &block)
|
54
|
+
def self.parse_stream(stream, data: nil, source_type: nil, type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, head: nil, **kargs, &block)
|
55
55
|
begin
|
56
56
|
bar = "Parsing #{Log.fingerprint stream}" if TrueClass === bar
|
57
57
|
bar = Log::ProgressBar.get_obj_bar(stream, bar) if bar
|
@@ -62,7 +62,8 @@ module TSV
|
|
62
62
|
data = {} if data.nil?
|
63
63
|
merge = false if type != :double && type != :flat
|
64
64
|
line = first_line || stream.gets
|
65
|
-
while line
|
65
|
+
while line
|
66
|
+
break if head && head <= 0
|
66
67
|
begin
|
67
68
|
line.chomp!
|
68
69
|
if Proc === fix
|
@@ -171,6 +172,7 @@ module TSV
|
|
171
172
|
stream.abort($!) if stream.respond_to?(:abort)
|
172
173
|
raise $!
|
173
174
|
ensure
|
175
|
+
head = head - 1 if head
|
174
176
|
if stream.closed?
|
175
177
|
line = nil
|
176
178
|
else
|
@@ -185,7 +187,15 @@ module TSV
|
|
185
187
|
else
|
186
188
|
bar.remove
|
187
189
|
end if bar
|
188
|
-
|
190
|
+
|
191
|
+
if stream.respond_to?(:join)
|
192
|
+
eof = begin
|
193
|
+
stream.eof?
|
194
|
+
rescue IOError
|
195
|
+
true
|
196
|
+
end
|
197
|
+
stream.join if eof
|
198
|
+
end
|
189
199
|
end
|
190
200
|
end
|
191
201
|
|
data/lib/scout/work_queue.rb
CHANGED
@@ -6,6 +6,7 @@ class WorkQueue
|
|
6
6
|
attr_accessor :workers, :worker_proc, :callback
|
7
7
|
|
8
8
|
def initialize(workers = 0, &block)
|
9
|
+
workers = workers.to_i if String === workers
|
9
10
|
@input = WorkQueue::Socket.new
|
10
11
|
@output = WorkQueue::Socket.new
|
11
12
|
@workers = workers.times.collect{ Worker.new }
|
@@ -6,7 +6,7 @@ module Workflow
|
|
6
6
|
return workload if job.done? && job.updated?
|
7
7
|
|
8
8
|
job.dependencies.each do |dep|
|
9
|
-
next if dep.done? &&
|
9
|
+
next if dep.done? && dep.updated?
|
10
10
|
workload.merge!(job_workload(dep))
|
11
11
|
workload[job] += workload[dep]
|
12
12
|
workload[job] << dep
|
@@ -14,7 +14,7 @@ module Workflow
|
|
14
14
|
end
|
15
15
|
|
16
16
|
job.input_dependencies.each do |dep|
|
17
|
-
next if dep.done? &&
|
17
|
+
next if dep.done? && dep.updated?
|
18
18
|
workload.merge!(job_workload(dep))
|
19
19
|
workload[job] += workload[dep]
|
20
20
|
workload[job] << dep
|
@@ -85,15 +85,15 @@ module Workflow
|
|
85
85
|
candidates = workload.
|
86
86
|
select{|k,v| v.empty? }.
|
87
87
|
collect{|k,v| k }.
|
88
|
-
reject{|k| k.done? }
|
88
|
+
reject{|k| k.done? || k.running? }
|
89
89
|
else
|
90
90
|
candidates = workload. #select{|k,v| Orchestrator.job_rules(rules, k) }.
|
91
91
|
select{|k,v| v.empty? }.
|
92
92
|
collect{|k,v| k }.
|
93
|
-
reject{|k| k.done? }
|
93
|
+
reject{|k| k.done? || k.running? }
|
94
94
|
end
|
95
95
|
|
96
|
-
top_level = workload.keys - workload.values.flatten
|
96
|
+
#top_level = workload.keys - workload.values.flatten
|
97
97
|
|
98
98
|
candidates = purge_duplicates candidates
|
99
99
|
candidates = sort_candidates candidates, rules
|
@@ -192,7 +192,10 @@ module Workflow
|
|
192
192
|
workload = Orchestrator.workload(jobs)
|
193
193
|
all_jobs = workload.keys
|
194
194
|
|
195
|
+
all_jobs.each{|job| job.clean unless job.done? && job.updated? }
|
196
|
+
|
195
197
|
top_level_jobs = jobs.collect{|job| job.path }
|
198
|
+
failed_jobs = []
|
196
199
|
while workload.any?
|
197
200
|
|
198
201
|
candidates = resources_used.keys + Orchestrator.candidates(workload, rules)
|
@@ -203,9 +206,15 @@ module Workflow
|
|
203
206
|
case
|
204
207
|
when (job.error? || job.aborted?)
|
205
208
|
begin
|
206
|
-
if job.recoverable_error?
|
207
|
-
job
|
208
|
-
|
209
|
+
if job.recoverable_error?
|
210
|
+
if failed_jobs.include?(job)
|
211
|
+
Log.warn "Failed twice #{job.path} with recoverable error"
|
212
|
+
next
|
213
|
+
else
|
214
|
+
failed_jobs << job
|
215
|
+
job.clean
|
216
|
+
raise TryAgain
|
217
|
+
end
|
209
218
|
else
|
210
219
|
next
|
211
220
|
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
class Step
|
2
|
-
def rec_dependencies
|
3
|
-
|
4
|
-
dependencies.
|
2
|
+
def rec_dependencies(connected = false, seen = [])
|
3
|
+
direct_deps = []
|
4
|
+
dependencies.each do |dep|
|
5
|
+
next if seen.include? dep.path
|
6
|
+
next if connected && dep.done? && dep.updated?
|
7
|
+
direct_deps << dep
|
8
|
+
end
|
9
|
+
seen.concat direct_deps.collect{|d| d.path }
|
10
|
+
direct_deps.inject(direct_deps){|acc,d| acc.concat(d.rec_dependencies(connected, [])); acc }
|
5
11
|
end
|
6
12
|
|
7
13
|
def recursive_inputs
|
@@ -127,6 +127,14 @@ class Step
|
|
127
127
|
! done? && (info[:pid] && Misc.pid_alive?(info[:pid]))
|
128
128
|
end
|
129
129
|
|
130
|
+
def overriden?
|
131
|
+
overriden_task || overriden_workflow || dependencies.select{|d| d.overriden? }.any?
|
132
|
+
end
|
133
|
+
|
134
|
+
def overriden_deps
|
135
|
+
rec_dependencies.select{|d| d.overriden? }
|
136
|
+
end
|
137
|
+
|
130
138
|
def exception
|
131
139
|
info[:exception]
|
132
140
|
end
|