rbbt-util 5.33.9 → 5.33.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/hpc/batch.rb +4 -4
- data/lib/rbbt/hpc/orchestrate/batches.rb +7 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +44 -38
- data/lib/rbbt/hpc/orchestrate.rb +1 -1
- data/lib/rbbt/util/misc/inspect.rb +1 -1
- data/lib/rbbt/util/misc/system.rb +2 -1
- data/lib/rbbt/workflow/dependencies.rb +4 -1
- data/lib/rbbt/workflow/step/accessor.rb +4 -0
- data/lib/rbbt/workflow/step/dependencies.rb +1 -1
- data/lib/rbbt/workflow/step/save_load_inputs.rb +48 -7
- data/lib/rbbt/workflow/step.rb +1 -1
- data/share/rbbt_commands/hpc/list +3 -1
- data/share/rbbt_commands/hpc/orchestrate +2 -1
- data/share/rbbt_commands/hpc/tail +1 -0
- data/share/rbbt_commands/lsf/list +3 -1
- data/share/rbbt_commands/lsf/orchestrate +2 -1
- data/share/rbbt_commands/lsf/tail +1 -0
- data/share/rbbt_commands/slurm/list +3 -1
- data/share/rbbt_commands/slurm/orchestrate +2 -1
- data/share/rbbt_commands/slurm/tail +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5c26a161d8529f19d32ace8b5565042b4baa6fef3d69580f46aadc523e8cc51
|
4
|
+
data.tar.gz: 8ee1305d3a66a55273474da60e84cec3385391ad99c8c87e764fd72eaaf29285
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b9ddf9ff821584ef21f7c30be381965ea9a8cf1cce7e9913cc11c118fa1d31211fe321d72c5d8daabcb14aac5b20df45c527fefa1d142c7a08633c3818b79dd
|
7
|
+
data.tar.gz: c0ab742b23fe87fd7f52bfdfe75690a02566547a34a484912c74766cff70c83634434d5a67a9e665bfdffb28be143afdb20028356befe045e19b14bcc83a21ff
|
data/lib/rbbt/hpc/batch.rb
CHANGED
@@ -88,8 +88,8 @@ module HPC
|
|
88
88
|
def rbbt_job_exec_cmd(job, options)
|
89
89
|
|
90
90
|
jobname = job.clean_name
|
91
|
-
workflow = job.workflow
|
92
|
-
task = job.task_name
|
91
|
+
workflow = job.original_workflow || job.workflow
|
92
|
+
task = job.original_task_name || job.task_name
|
93
93
|
|
94
94
|
Misc.add_defaults options, :jobname => jobname
|
95
95
|
|
@@ -535,8 +535,8 @@ env > #{batch_options[:fenv]}
|
|
535
535
|
:batch_base_dir, :clean_batch_job, :remove_batch_dir, :batch_procpath, :tail, :batch_dependencies, :dry_run,
|
536
536
|
:batch_base_dir => File.expand_path(File.join('~/rbbt-batch'))
|
537
537
|
|
538
|
-
workflow = job.workflow
|
539
|
-
task_name = job.task_name
|
538
|
+
workflow = job.original_workflow ||job.workflow
|
539
|
+
task_name = job.original_task_name || job.task_name
|
540
540
|
|
541
541
|
workflows_to_load = job.rec_dependencies.select{|d| Step === d}.collect{|d| d.workflow }.compact.collect(&:to_s) - [workflow.to_s]
|
542
542
|
|
@@ -101,7 +101,9 @@ module HPC
|
|
101
101
|
|
102
102
|
batches.each do |batch|
|
103
103
|
job_rules = batch[:jobs].inject(nil) do |acc,job|
|
104
|
-
|
104
|
+
workflow = job.original_workflow || job.workflow
|
105
|
+
task_name = job.original_task_name || job.task_name
|
106
|
+
task_rules = task_specific_rules(rules, workflow, task_name)
|
105
107
|
acc = accumulate_rules(acc, task_rules.dup)
|
106
108
|
end
|
107
109
|
|
@@ -120,13 +122,16 @@ module HPC
|
|
120
122
|
end
|
121
123
|
|
122
124
|
batches.each do |batch|
|
125
|
+
next if batch[:top_level].overriden?
|
123
126
|
next unless batch[:rules][:skip]
|
124
127
|
batch[:rules].delete :skip
|
125
128
|
next if batch[:deps].nil?
|
126
129
|
|
127
130
|
if batch[:deps].any?
|
131
|
+
batch_dep_jobs = batch[:top_level].rec_dependencies
|
128
132
|
target = batch[:deps].select do |target|
|
129
|
-
(
|
133
|
+
batch_dep_jobs.include?(target[:top_level]) && # Don't piggyback batches that are an input dependency, only real dependencies
|
134
|
+
(batch[:deps] - [target] - target[:deps]).empty?
|
130
135
|
end.first
|
131
136
|
next if target.nil?
|
132
137
|
target[:jobs] = batch[:jobs] + target[:jobs]
|
@@ -4,8 +4,10 @@ module HPC
|
|
4
4
|
return [] if Symbol === job.overriden
|
5
5
|
matches = []
|
6
6
|
chains.each do |name, chain|
|
7
|
-
|
8
|
-
|
7
|
+
workflow = job.original_workflow || job.workflow
|
8
|
+
task_name = job.original_task_name || job.task_name
|
9
|
+
next unless chain[:tasks].include?(workflow.to_s)
|
10
|
+
next unless chain[:tasks][workflow.to_s].include?(task_name.to_s)
|
9
11
|
matches << name
|
10
12
|
end
|
11
13
|
matches
|
@@ -38,46 +40,50 @@ module HPC
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def self.job_chains(rules, job)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
found
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
43
|
+
@@job_chains ||= {}
|
44
|
+
@@job_chains[Misc.digest([rules, job.path].inspect)] ||=
|
45
|
+
begin
|
46
|
+
chains = self.parse_chains(rules)
|
47
|
+
|
48
|
+
matches = check_chains(chains, job)
|
49
|
+
|
50
|
+
dependencies = job_dependencies(job)
|
51
|
+
|
52
|
+
job_chains = []
|
53
|
+
new_job_chains = {}
|
54
|
+
dependencies.each do |dep|
|
55
|
+
dep_matches = check_chains(chains, dep)
|
56
|
+
common = matches & dep_matches
|
57
|
+
|
58
|
+
dep_chains = job_chains(rules, dep)
|
59
|
+
found = []
|
60
|
+
dep_chains.each do |match,info|
|
61
|
+
if common.include?(match)
|
62
|
+
found << match
|
63
|
+
new_info = new_job_chains[match] ||= {}
|
64
|
+
new_info[:jobs] ||= []
|
65
|
+
new_info[:jobs].concat info[:jobs]
|
66
|
+
new_info[:top_level] = job
|
67
|
+
else
|
68
|
+
job_chains << [match, info]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
(common - found).each do |match|
|
73
|
+
info = {}
|
74
|
+
info[:jobs] = [job, dep]
|
75
|
+
info[:top_level] = job
|
76
|
+
job_chains << [match, info]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
new_job_chains.each do |match,info|
|
81
|
+
info[:jobs].prepend job
|
63
82
|
job_chains << [match, info]
|
64
83
|
end
|
65
|
-
end
|
66
84
|
|
67
|
-
|
68
|
-
info = {}
|
69
|
-
info[:jobs] = [job, dep]
|
70
|
-
info[:top_level] = job
|
71
|
-
job_chains << [match, info]
|
85
|
+
job_chains
|
72
86
|
end
|
73
|
-
end
|
74
|
-
|
75
|
-
new_job_chains.each do |match,info|
|
76
|
-
info[:jobs].prepend job
|
77
|
-
job_chains << [match, info]
|
78
|
-
end
|
79
|
-
|
80
|
-
job_chains
|
81
87
|
end
|
82
88
|
|
83
89
|
end
|
data/lib/rbbt/hpc/orchestrate.rb
CHANGED
@@ -82,7 +82,7 @@ module HPC
|
|
82
82
|
|
83
83
|
if options[:dry_run]
|
84
84
|
puts Log.color(:magenta, "Manifest: ") + Log.color(:blue, job_options[:manifest] * ", ") + " - tasks: #{job_options[:task_cpus] || 1} - time: #{job_options[:time]} - config: #{job_options[:config_keys]}"
|
85
|
-
puts Log.color(:
|
85
|
+
puts Log.color(:yellow, "Deps: ") + Log.color(:blue, job_options[:batch_dependencies]*", ")
|
86
86
|
puts Log.color(:yellow, "Path: ") + top[:top_level].path
|
87
87
|
puts Log.color(:yellow, "Options: ") + job_options.inspect
|
88
88
|
batch_ids[top] = top[:top_level].task_signature
|
@@ -355,7 +355,7 @@ module Misc
|
|
355
355
|
"<IO:" << obj.path << "--" << mtime_str(obj.path) << ">"
|
356
356
|
end
|
357
357
|
when (defined? Step and Step)
|
358
|
-
"<IO:" << obj.
|
358
|
+
"<IO:" << obj.short_path_real << ">"
|
359
359
|
when IO
|
360
360
|
if obj.respond_to? :filename and obj.filename
|
361
361
|
if defined?(Step) && Open.exists?(Step.info_file(obj.filename))
|
@@ -113,9 +113,10 @@ end
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def self.is_filename?(string, need_to_exists = true)
|
116
|
+
return false if string.nil?
|
116
117
|
return true if defined? Path and Path === string
|
117
118
|
return true if string.respond_to? :exists
|
118
|
-
return true if String === string and string.length
|
119
|
+
return true if String === string and string.split("/").select{|p| p.length > 265}.empty? and (! need_to_exists || File.exist?(string))
|
119
120
|
return false
|
120
121
|
end
|
121
122
|
|
@@ -72,9 +72,12 @@ module Workflow
|
|
72
72
|
def setup_override_dependency(dep, workflow, task_name)
|
73
73
|
return [] if dep == :skip || dep == 'skip'
|
74
74
|
dep = Step === dep ? dep.dup : Workflow.load_step(dep)
|
75
|
+
|
76
|
+
dep.original_workflow ||= dep.workflow if dep.workflow
|
77
|
+
dep.original_task_name ||= dep.task_name if dep.workflow
|
78
|
+
|
75
79
|
dep.workflow = workflow
|
76
80
|
dep.info[:name] = dep.name
|
77
|
-
dep.original_task_name ||= dep.task_name if dep.workflow
|
78
81
|
|
79
82
|
|
80
83
|
begin
|
@@ -96,6 +96,10 @@ class Step
|
|
96
96
|
[task_name, name] * "/"
|
97
97
|
end
|
98
98
|
|
99
|
+
def short_path_real
|
100
|
+
[(Symbol === overriden ? overriden : task_name).to_s, name] * "/"
|
101
|
+
end
|
102
|
+
|
99
103
|
def workflow_short_path
|
100
104
|
return short_path unless workflow
|
101
105
|
workflow.to_s + "#" + short_path
|
@@ -510,7 +510,7 @@ class Step
|
|
510
510
|
|
511
511
|
def overriden?
|
512
512
|
return true if @overriden
|
513
|
-
return true if dependencies.select{|dep| dep.overriden? }.any?
|
513
|
+
return true if dependencies && dependencies.select{|dep| dep.overriden? }.any?
|
514
514
|
info[:archived_info].each do |f,i|
|
515
515
|
next if Symbol === i
|
516
516
|
return true if i[:overriden] || i["overriden"]
|
@@ -21,16 +21,24 @@ module Workflow
|
|
21
21
|
Log.debug "Trying #{ input }: #{file}"
|
22
22
|
next unless file and (File.symlink?(file) || file.exists?)
|
23
23
|
|
24
|
-
type = input_types[input]
|
24
|
+
type = orig_type = input_types[input]
|
25
25
|
|
26
26
|
type = :io if file.split(".").last == 'as_io'
|
27
27
|
|
28
|
+
type = :io_array if file.split(".").last == 'as_io_array'
|
29
|
+
|
28
30
|
type = :step if file.split(".").last == 'as_step'
|
29
31
|
|
32
|
+
type = :step_array if file.split(".").last == 'as_step_array'
|
33
|
+
|
30
34
|
type = :step_file if file.split(".").last == 'as_step_file'
|
31
35
|
|
36
|
+
type = :step_file_array if file.split(".").last == 'as_step_file_array'
|
37
|
+
|
32
38
|
type = :path if file.split(".").last == 'as_path'
|
33
39
|
|
40
|
+
type = :path_array if file.split(".").last == 'as_path_array'
|
41
|
+
|
34
42
|
type = :filename if file.split(".").last == 'as_filename'
|
35
43
|
|
36
44
|
type = :nofile if file.split(".").last == 'nofile'
|
@@ -38,18 +46,34 @@ module Workflow
|
|
38
46
|
case type
|
39
47
|
when :nofile
|
40
48
|
inputs[input.to_sym] = Open.realpath(file)
|
49
|
+
when :path_array
|
50
|
+
inputs[input.to_sym] = Open.read(file).strip.split("\n")
|
41
51
|
when :path
|
42
|
-
inputs[input.to_sym] = Open.read(file).strip
|
52
|
+
inputs[input.to_sym] = Open.read(file).strip.split("\n").first
|
53
|
+
when :io
|
54
|
+
inputs[input.to_sym] = Open.open(Open.realpath(file)).split("\n")
|
43
55
|
when :io
|
44
|
-
inputs[input.to_sym] = Open.
|
56
|
+
inputs[input.to_sym] = Open.realpath(file).split("\n").collect{|f| Open.open(f)}
|
57
|
+
when :step_array
|
58
|
+
steps = Open.read(file).strip.split("\n").collect{|path| Workflow.load_step(path) }
|
59
|
+
inputs[input.to_sym] = steps
|
45
60
|
when :step
|
46
|
-
|
61
|
+
steps = Open.read(file).strip.split("\n").collect{|path| Workflow.load_step(path) }
|
62
|
+
inputs[input.to_sym] = steps.first
|
47
63
|
when :step_file
|
48
64
|
path = Open.read(file).strip
|
49
65
|
path.extend Path
|
50
66
|
step_path = path.match(/(.*)\.files/)[1]
|
51
67
|
path.resource = Step.new step_path
|
52
68
|
inputs[input.to_sym] = path
|
69
|
+
when :step_file_array
|
70
|
+
paths = Open.read(file).split("\n")
|
71
|
+
paths.each do |path|
|
72
|
+
path.extend Path
|
73
|
+
step_path = path.match(/(.*)\.files/)[1]
|
74
|
+
path.resource = Step.new step_path
|
75
|
+
end
|
76
|
+
inputs[input.to_sym] = paths
|
53
77
|
when :file, :binary
|
54
78
|
Log.debug "Pointing #{ input } to #{file}"
|
55
79
|
if file =~ /\.yaml/
|
@@ -187,7 +211,6 @@ class Step
|
|
187
211
|
def self.save_input(name, value, type, dir)
|
188
212
|
path = File.join(dir, name.to_s)
|
189
213
|
|
190
|
-
|
191
214
|
case value
|
192
215
|
when Path
|
193
216
|
if Step === value.resource
|
@@ -207,6 +230,24 @@ class Step
|
|
207
230
|
value = value.path
|
208
231
|
path = path + '.as_step'
|
209
232
|
when Array
|
233
|
+
case value.first
|
234
|
+
when Path
|
235
|
+
if Step === value.first.resource
|
236
|
+
path = path + '.as_step_file_array'
|
237
|
+
else
|
238
|
+
path = path + '.as_path_array'
|
239
|
+
end
|
240
|
+
when String
|
241
|
+
if Misc.is_filename?(value.first, false)
|
242
|
+
path = path + '.as_path_array'
|
243
|
+
end
|
244
|
+
when IO
|
245
|
+
path = path + '.as_io_array'
|
246
|
+
when Step
|
247
|
+
path = path + '.as_step_array'
|
248
|
+
value = value.collect{|s| s.path }
|
249
|
+
end
|
250
|
+
|
210
251
|
value = value * "\n"
|
211
252
|
end
|
212
253
|
|
@@ -226,8 +267,8 @@ class Step
|
|
226
267
|
def self.save_job_inputs(job, dir, options = nil)
|
227
268
|
options = IndiferentHash.setup options.dup if options
|
228
269
|
|
229
|
-
task_name =
|
230
|
-
workflow = job.workflow
|
270
|
+
task_name = job.original_task_name || job.task_name
|
271
|
+
workflow = job.original_workflow || job.workflow
|
231
272
|
workflow = Kernel.const_get workflow if String === workflow
|
232
273
|
if workflow
|
233
274
|
task_info = IndiferentHash.setup(workflow.task_info(task_name))
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -15,7 +15,7 @@ class Step
|
|
15
15
|
attr_accessor :exec
|
16
16
|
attr_accessor :relocated
|
17
17
|
attr_accessor :result, :mutex, :seen
|
18
|
-
attr_accessor :real_inputs, :original_task_name
|
18
|
+
attr_accessor :real_inputs, :original_task_name, :original_workflow
|
19
19
|
|
20
20
|
RBBT_DEBUG_CLEAN = ENV["RBBT_DEBUG_CLEAN"] == 'true'
|
21
21
|
|
@@ -209,7 +209,9 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
209
209
|
if j.file(:progress).exists?
|
210
210
|
bar = Log::ProgressBar.new
|
211
211
|
bar.load(j.file(:progress).yaml)
|
212
|
-
|
212
|
+
rep = bar.report_msg.split("·")[1]
|
213
|
+
rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
|
214
|
+
prog_rep << [rep]
|
213
215
|
end
|
214
216
|
end
|
215
217
|
end
|
@@ -60,5 +60,6 @@ class Step
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
ARGV.concat [
|
63
|
+
ARGV.concat ['--detach']
|
64
|
+
ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
|
64
65
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
@@ -209,7 +209,9 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
209
209
|
if j.file(:progress).exists?
|
210
210
|
bar = Log::ProgressBar.new
|
211
211
|
bar.load(j.file(:progress).yaml)
|
212
|
-
|
212
|
+
rep = bar.report_msg.split("·")[1]
|
213
|
+
rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
|
214
|
+
prog_rep << [rep]
|
213
215
|
end
|
214
216
|
end
|
215
217
|
end
|
@@ -60,5 +60,6 @@ class Step
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
ARGV.concat [
|
63
|
+
ARGV.concat ['--detach']
|
64
|
+
ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
|
64
65
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
@@ -209,7 +209,9 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
209
209
|
if j.file(:progress).exists?
|
210
210
|
bar = Log::ProgressBar.new
|
211
211
|
bar.load(j.file(:progress).yaml)
|
212
|
-
|
212
|
+
rep = bar.report_msg.split("·")[1]
|
213
|
+
rep = rep.sub(/.*?(\d+%)/, Log.color(:blue,'\1')).sub(/\-.*/,'')
|
214
|
+
prog_rep << [rep]
|
213
215
|
end
|
214
216
|
end
|
215
217
|
end
|
@@ -60,5 +60,6 @@ class Step
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
ARGV.concat [
|
63
|
+
ARGV.concat ['--detach']
|
64
|
+
ARGV.concat ["-W", $slurm_options[:workflows]] if $slurm_options[:workflows]
|
64
65
|
load Rbbt.share.rbbt_commands.workflow.task.find
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.33.
|
4
|
+
version: 5.33.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|