scout-gear 10.7.0 → 10.7.2
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 +8 -1
- data/VERSION +1 -1
- data/lib/scout/association/index.rb +1 -1
- data/lib/scout/association.rb +21 -5
- data/lib/scout/entity/format.rb +9 -4
- data/lib/scout/entity/identifiers.rb +2 -2
- data/lib/scout/entity/named_array.rb +13 -0
- data/lib/scout/entity/property.rb +2 -1
- data/lib/scout/entity.rb +9 -4
- data/lib/scout/persist/tsv/adapter/base.rb +13 -1
- data/lib/scout/persist/tsv.rb +2 -1
- data/lib/scout/tsv/attach.rb +10 -2
- data/lib/scout/tsv/change_id.rb +3 -0
- data/lib/scout/tsv/dumper.rb +34 -30
- data/lib/scout/tsv/open.rb +1 -0
- data/lib/scout/tsv/parser.rb +22 -10
- data/lib/scout/tsv/path.rb +8 -0
- data/lib/scout/tsv/stream.rb +15 -8
- data/lib/scout/tsv/traverse.rb +12 -2
- data/lib/scout/tsv/util/process.rb +4 -1
- data/lib/scout/tsv/util/select.rb +8 -2
- data/lib/scout/tsv/util/sort.rb +23 -15
- data/lib/scout/tsv/util.rb +11 -2
- data/lib/scout/tsv.rb +23 -11
- data/lib/scout/workflow/definition.rb +24 -9
- data/lib/scout/workflow/deployment/orchestrator.rb +10 -7
- data/lib/scout/workflow/exceptions.rb +1 -0
- data/lib/scout/workflow/path.rb +40 -0
- data/lib/scout/workflow/step/dependencies.rb +36 -12
- data/lib/scout/workflow/step/file.rb +2 -1
- data/lib/scout/workflow/step/info.rb +20 -4
- data/lib/scout/workflow/step/load.rb +5 -3
- data/lib/scout/workflow/step/progress.rb +6 -0
- data/lib/scout/workflow/step/provenance.rb +1 -1
- data/lib/scout/workflow/step/status.rb +11 -4
- data/lib/scout/workflow/step.rb +33 -12
- data/lib/scout/workflow/task/dependencies.rb +33 -24
- data/lib/scout/workflow/task/inputs.rb +42 -12
- data/lib/scout/workflow/task.rb +22 -11
- data/lib/scout/workflow/usage.rb +3 -3
- data/lib/scout/workflow.rb +3 -0
- data/scout-gear.gemspec +13 -4
- data/scout_commands/db/query +83 -0
- data/scout_commands/db/register +43 -0
- data/scout_commands/db/show +47 -0
- data/test/scout/entity/test_named_array.rb +21 -0
- data/test/scout/persist/test_tsv.rb +20 -0
- data/test/scout/persist/tsv/adapter/test_base.rb +20 -0
- data/test/scout/test_tsv.rb +40 -0
- data/test/scout/tsv/test_dumper.rb +24 -0
- data/test/scout/tsv/test_path.rb +24 -0
- data/test/scout/tsv/test_stream.rb +93 -0
- data/test/scout/tsv/test_traverse.rb +99 -0
- data/test/scout/tsv/test_util.rb +2 -0
- data/test/scout/tsv/util/test_select.rb +22 -0
- data/test/scout/tsv/util/test_sort.rb +24 -0
- data/test/scout/workflow/step/test_dependencies.rb +26 -0
- data/test/scout/workflow/step/test_info.rb +35 -0
- data/test/scout/workflow/task/test_dependencies.rb +67 -1
- data/test/scout/workflow/task/test_inputs.rb +24 -7
- data/test/scout/workflow/test_definition.rb +31 -0
- data/test/scout/workflow/test_path.rb +9 -0
- data/test/scout/workflow/test_task.rb +36 -0
- data/test/scout/workflow/test_usage.rb +0 -1
- metadata +12 -3
@@ -44,11 +44,14 @@ module TSV
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def add_field(name = nil)
|
47
|
-
|
47
|
+
keys.each do |key|
|
48
|
+
values = self[key]
|
48
49
|
new_values = yield(key, values)
|
49
50
|
new_values = [new_values].compact if type == :double and not Array === new_values
|
50
51
|
|
51
52
|
case
|
53
|
+
when type == :single
|
54
|
+
values = new_values
|
52
55
|
when (values.nil? and (fields.nil? or fields.empty?))
|
53
56
|
values = [new_values]
|
54
57
|
when values.nil?
|
@@ -156,8 +156,14 @@ module TSV
|
|
156
156
|
case
|
157
157
|
when ((Array === method) and (key == :key or key_field == key))
|
158
158
|
with_unnamed do
|
159
|
-
|
160
|
-
|
159
|
+
if invert
|
160
|
+
keys.each do |key|
|
161
|
+
new[key] = self[key] unless method.include?(key)
|
162
|
+
end
|
163
|
+
else
|
164
|
+
method.each do |key|
|
165
|
+
new[key] = self[key] if self.include?(key)
|
166
|
+
end
|
161
167
|
end
|
162
168
|
end
|
163
169
|
when Array === method
|
data/lib/scout/tsv/util/sort.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
+
require 'scout/entity'
|
2
|
+
|
1
3
|
module TSV
|
4
|
+
def prepare_entity(...)
|
5
|
+
Entity.prepare_entity(...)
|
6
|
+
end
|
7
|
+
|
2
8
|
def sort_by(field = nil, just_keys = false, &block)
|
3
9
|
field = :all if field.nil?
|
4
10
|
|
@@ -8,16 +14,18 @@ module TSV
|
|
8
14
|
elems = []
|
9
15
|
case type
|
10
16
|
when :single
|
11
|
-
through :key, field do |key,
|
12
|
-
elems << [key,
|
17
|
+
through :key, field do |key, value|
|
18
|
+
elems << [key, value]
|
13
19
|
end
|
14
20
|
when :list, :flat
|
15
|
-
through :key, field do |key,
|
16
|
-
|
21
|
+
through :key, field do |key, value|
|
22
|
+
v = field == :key ? key : value[0]
|
23
|
+
elems << [key, v]
|
17
24
|
end
|
18
25
|
when :double
|
19
|
-
through :key, field do |key,
|
20
|
-
|
26
|
+
through :key, field do |key, value|
|
27
|
+
v = field == :key ? key : value[0]
|
28
|
+
elems << [key, v]
|
21
29
|
end
|
22
30
|
end
|
23
31
|
end
|
@@ -81,16 +89,16 @@ module TSV
|
|
81
89
|
elems = []
|
82
90
|
case type
|
83
91
|
when :single
|
84
|
-
through :key, field do |key,
|
85
|
-
elems << [key,
|
92
|
+
through :key, field do |key, value|
|
93
|
+
elems << [key, value]
|
86
94
|
end
|
87
95
|
when :list, :flat
|
88
|
-
through :key, field do |key,
|
89
|
-
elems << [key,
|
96
|
+
through :key, field do |key, values|
|
97
|
+
elems << [key, values[0]]
|
90
98
|
end
|
91
99
|
when :double
|
92
|
-
through :key, field do |key,
|
93
|
-
elems << [key,
|
100
|
+
through :key, field do |key, values|
|
101
|
+
elems << [key, values[0]]
|
94
102
|
end
|
95
103
|
end
|
96
104
|
end
|
@@ -99,7 +107,7 @@ module TSV
|
|
99
107
|
if fields == :all
|
100
108
|
if just_keys
|
101
109
|
keys = elems.sort_by{|key, value| key }.collect{|key, values| key}
|
102
|
-
keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true))
|
110
|
+
keys = prepare_entity(keys, key_field, (entity_options || {}).merge(:dup_array => true))
|
103
111
|
else
|
104
112
|
elems.sort_by{|key, value| key }
|
105
113
|
end
|
@@ -128,7 +136,7 @@ module TSV
|
|
128
136
|
end
|
129
137
|
if just_keys
|
130
138
|
keys = sorted.collect{|key, value| key}
|
131
|
-
keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true)) unless @unnamed
|
139
|
+
keys = prepare_entity(keys, key_field, (entity_options || {}).merge(:dup_array => true)) unless @unnamed
|
132
140
|
keys
|
133
141
|
else
|
134
142
|
sorted.collect{|key, value| [key, self[key]]}
|
@@ -137,7 +145,7 @@ module TSV
|
|
137
145
|
else
|
138
146
|
if just_keys
|
139
147
|
keys = elems.sort(&block).collect{|key, value| key}
|
140
|
-
keys = prepare_entity(keys, key_field, entity_options.merge(:dup_array => true)) unless @unnamed
|
148
|
+
keys = prepare_entity(keys, key_field, (entity_options || {}).merge(:dup_array => true)) unless @unnamed
|
141
149
|
keys
|
142
150
|
else
|
143
151
|
elems.sort(&block).collect{|key, value| [key, self[key]]}
|
data/lib/scout/tsv/util.rb
CHANGED
@@ -32,6 +32,7 @@ module TSV
|
|
32
32
|
text
|
33
33
|
end
|
34
34
|
|
35
|
+
path = path.find if Path === path
|
35
36
|
TmpFile.with_file(values.uniq * "\n", false) do |value_file|
|
36
37
|
cmd = "cat '#{ path }' | sed 's/\\t/\\tHEADERNOMATCH/' | grep -w -F -f '#{ value_file }' | sed 's/HEADERNOMATCH//' |sort -u|cut -f 2 |sort|uniq -c|sed 's/^ *//;s/ /\t/'"
|
37
38
|
begin
|
@@ -84,8 +85,9 @@ module TSV
|
|
84
85
|
|
85
86
|
def each(*args, &block)
|
86
87
|
if block_given?
|
88
|
+
actual_unnamed = @unnamed.nil? ? true : @unnamed
|
87
89
|
super(*args) do |k,v|
|
88
|
-
NamedArray.setup(v, @fields) unless
|
90
|
+
NamedArray.setup(v, @fields) unless actual_unnamed || @type == :flat || ! (Array === v)
|
89
91
|
block.call(k, v)
|
90
92
|
end
|
91
93
|
else
|
@@ -105,7 +107,8 @@ module TSV
|
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
|
-
def with_unnamed(unnamed =
|
110
|
+
def with_unnamed(unnamed = nil)
|
111
|
+
unnamed = true if unnamed.nil?
|
109
112
|
begin
|
110
113
|
old_unnamed = @unnamed
|
111
114
|
@unnamed = unnamed
|
@@ -177,4 +180,10 @@ Example:
|
|
177
180
|
self.annotate(super(other))
|
178
181
|
end
|
179
182
|
|
183
|
+
def merge_zip(other)
|
184
|
+
other.each do |k,v|
|
185
|
+
self.zip_new k, v
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
180
189
|
end
|
data/lib/scout/tsv.rb
CHANGED
@@ -16,7 +16,8 @@ require_relative 'tsv/csv'
|
|
16
16
|
|
17
17
|
module TSV
|
18
18
|
extend Annotation
|
19
|
-
annotation :key_field, :fields, :type, :cast, :filename, :namespace, :unnamed, :identifiers, :serializer
|
19
|
+
annotation :key_field, :fields, :type, :cast, :filename, :namespace, :unnamed, :identifiers, :serializer, :entity_options
|
20
|
+
|
20
21
|
|
21
22
|
def self.str2options(str)
|
22
23
|
field_options,_sep, rest = str.partition("#")
|
@@ -34,7 +35,6 @@ module TSV
|
|
34
35
|
alias original_setup setup
|
35
36
|
|
36
37
|
def setup(obj, *rest, &block)
|
37
|
-
|
38
38
|
if rest.length == 1 && String === rest.first
|
39
39
|
options = TSV.str2options(rest.first)
|
40
40
|
if Array === obj
|
@@ -44,7 +44,7 @@ module TSV
|
|
44
44
|
when :single
|
45
45
|
nil
|
46
46
|
end
|
47
|
-
obj =
|
47
|
+
obj = IndiferentHash.array2hash(obj, default_value)
|
48
48
|
end
|
49
49
|
original_setup(obj, options, &block)
|
50
50
|
else
|
@@ -57,7 +57,7 @@ module TSV
|
|
57
57
|
when :single
|
58
58
|
nil
|
59
59
|
end
|
60
|
-
obj =
|
60
|
+
obj = IndiferentHash.array2hash(obj, default_value)
|
61
61
|
end
|
62
62
|
original_setup(obj, *rest, &block)
|
63
63
|
end
|
@@ -74,11 +74,17 @@ module TSV
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def self.open(file, options = {})
|
77
|
-
grep, invert_grep, nocache, monitor, entity_options = IndiferentHash.process_options options, :grep, :invert_grep, :nocache, :monitor, :entity_options
|
77
|
+
grep, invert_grep, fixed_grep, nocache, monitor, entity_options, unnamed, field = IndiferentHash.process_options options, :grep, :invert_grep, :fixed_grep, :nocache, :monitor, :entity_options, :unnamed, :field
|
78
|
+
|
79
|
+
if field and options[:field].nil?
|
80
|
+
options[:fields] = [field]
|
81
|
+
options[:type] ||= :single
|
82
|
+
end
|
78
83
|
|
79
84
|
persist_options = IndiferentHash.pull_keys options, :persist
|
80
85
|
persist_options = IndiferentHash.add_defaults persist_options, prefix: "TSV", type: :HDB, persist: false
|
81
86
|
persist_options[:data] ||= options[:data]
|
87
|
+
persist_options[:update] = options.delete(:update) if options.include?(:update)
|
82
88
|
|
83
89
|
file = StringIO.new file if String === file && ! (Path === file) && file.index("\n")
|
84
90
|
|
@@ -113,14 +119,20 @@ module TSV
|
|
113
119
|
end
|
114
120
|
|
115
121
|
tsv = if TSV::Parser === file
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
+
TSV.parse(file, **options)
|
123
|
+
else
|
124
|
+
options[:tsv_invert_grep] ||= invert_grep if invert_grep
|
125
|
+
Open.open(file, grep: grep, invert_grep: invert_grep, fixed_grep: fixed_grep, nocache: nocache) do |f|
|
126
|
+
TSV.parse(f, **options)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
if tsv.identifiers.nil? and Path === tsv.filename and tsv.filename.identifier_file_path
|
131
|
+
tsv.identifiers = tsv.filename.identifier_file_path.find if tsv.filename.identifier_file_path.exists?
|
122
132
|
end
|
123
133
|
|
134
|
+
tsv.unnamed = unnamed unless unnamed.nil?
|
135
|
+
|
124
136
|
tsv
|
125
137
|
end
|
126
138
|
end
|
@@ -140,8 +140,17 @@ module Workflow
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
-
|
144
|
-
|
143
|
+
FORGET_TASK_ALIAS = begin
|
144
|
+
%w(SCOUT_FORGET_TASK_ALIAS SCOUT_FORGET_DEP_TASKS RBBT_FORGET_DEP_TASKS).select do |var|
|
145
|
+
ENV[var] == 'true'
|
146
|
+
end.any?
|
147
|
+
end
|
148
|
+
REMOVE_TASK_ALIAS = begin
|
149
|
+
remove = %w(SCOUT_REMOVE_TASK_ALIAS SCOUT_REMOVE_DEP_TASKS RBBT_REMOVE_DEP_TASKS).select do |var|
|
150
|
+
ENV.include?(var) && ENV[var] != 'false'
|
151
|
+
end.first
|
152
|
+
remove.nil? ? false : remove
|
153
|
+
end
|
145
154
|
def task_alias(name, workflow, oname, *rest, &block)
|
146
155
|
dep(workflow, oname, *rest, &block)
|
147
156
|
extension :dep_task unless @extension
|
@@ -155,18 +164,24 @@ module Workflow
|
|
155
164
|
Step.wait_for_jobs dependencies.select{|d| d.streaming? }
|
156
165
|
dep = dependencies.last
|
157
166
|
dep.join
|
158
|
-
raise dep.
|
167
|
+
raise dep.exception if dep.error?
|
159
168
|
raise Aborted, "Aborted dependency #{dep.path}" if dep.aborted?
|
160
|
-
|
161
|
-
|
169
|
+
merge_info type: dep.info[:type], task_alias: true
|
170
|
+
|
171
|
+
forget = config :forget_task_alias, "forget_task_alias"
|
172
|
+
forget = config :forget_dep_tasks, "forget_dep_tasks", :default => FORGET_TASK_ALIAS if forget.nil?
|
173
|
+
|
162
174
|
if forget
|
163
|
-
remove = config :
|
175
|
+
remove = config :remove_task_alias, "remove_task_alias"
|
176
|
+
remove = config :remove_dep_tasks, "remove_dep_tasks", :default => REMOVE_TASK_ALIAS if remove.nil?
|
177
|
+
|
178
|
+
Log.medium "Forget task_alias (remove: #{remove}): #{short_path}"
|
164
179
|
|
165
180
|
self.archive_deps
|
166
181
|
self.copy_linked_files_dir
|
167
182
|
self.dependencies = self.dependencies - [dep]
|
168
183
|
Open.rm_rf self.files_dir if Open.exist? self.files_dir
|
169
|
-
|
184
|
+
Open.link_dir dep.files_dir, self.files_dir if Open.exist?(dep.files_dir)
|
170
185
|
|
171
186
|
if dep.overriden?
|
172
187
|
Open.link dep.path, self.tmp_path
|
@@ -179,9 +194,9 @@ module Workflow
|
|
179
194
|
when 'recursive'
|
180
195
|
(dep.dependencies + dep.rec_dependencies).uniq.each do |d|
|
181
196
|
next if d.overriden
|
182
|
-
d.clean unless
|
197
|
+
d.clean unless Scout::Config.get(:remove_dep, "task:#{d.task_signature}", "task:#{d.task_name}", "workflow:#{d.workflow.name}", :default => true).to_s == 'false'
|
183
198
|
end
|
184
|
-
dep.clean unless
|
199
|
+
dep.clean unless Scout::Config.get(:remove_dep, "task:#{dep.task_signature}", "task:#{dep.task_name}", "workflow:#{dep.workflow.name}", :default => true).to_s == 'false'
|
185
200
|
end
|
186
201
|
end
|
187
202
|
else
|
@@ -34,14 +34,16 @@ module Workflow
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.job_rules(rules, job)
|
37
|
+
IndiferentHash.setup(rules)
|
37
38
|
workflow = job.workflow.name
|
38
39
|
task_name = job.task_name.to_s
|
39
40
|
defaults = rules["defaults"] || {}
|
40
41
|
|
41
42
|
return IndiferentHash.setup(defaults) unless rules[workflow]
|
42
|
-
|
43
|
+
workflow_rules = IndiferentHash.setup(rules[workflow])
|
44
|
+
return IndiferentHash.setup(defaults) unless workflow_rules[task_name]
|
45
|
+
job_rules = IndiferentHash.setup(workflow_rules[task_name])
|
43
46
|
|
44
|
-
job_rules = IndiferentHash.setup(rules[workflow][task_name])
|
45
47
|
defaults.each{|k,v| job_rules[k] = v if job_rules[k].nil? } if defaults
|
46
48
|
job_rules
|
47
49
|
end
|
@@ -85,7 +87,7 @@ module Workflow
|
|
85
87
|
candidates = workload.
|
86
88
|
select{|k,v| v.empty? }.
|
87
89
|
collect{|k,v| k }.
|
88
|
-
reject{|k| k.done? || k.running? }
|
90
|
+
reject{|k| k.done? || k.running? || (k.error? && ! k.recoverable_error?) }
|
89
91
|
else
|
90
92
|
candidates = workload. #select{|k,v| Orchestrator.job_rules(rules, k) }.
|
91
93
|
select{|k,v| v.empty? }.
|
@@ -107,7 +109,7 @@ module Workflow
|
|
107
109
|
|
108
110
|
attr_accessor :available_resources, :resources_requested, :resources_used, :timer
|
109
111
|
|
110
|
-
def initialize(timer = 5, available_resources =
|
112
|
+
def initialize(timer = 5, available_resources = nil)
|
111
113
|
available_resources = {:cpus => Etc.nprocessors } if available_resources.nil?
|
112
114
|
@timer = timer
|
113
115
|
@available_resources = IndiferentHash.setup(available_resources)
|
@@ -192,7 +194,7 @@ module Workflow
|
|
192
194
|
workload = Orchestrator.workload(jobs)
|
193
195
|
all_jobs = workload.keys
|
194
196
|
|
195
|
-
all_jobs.each{|job| job.clean unless job.done? && job.updated? }
|
197
|
+
all_jobs.each{|job| job.clean unless (job.done? && job.updated?) || (job.error? && ! job.recoverable_error?) }
|
196
198
|
|
197
199
|
top_level_jobs = jobs.collect{|job| job.path }
|
198
200
|
failed_jobs = []
|
@@ -216,6 +218,7 @@ module Workflow
|
|
216
218
|
raise TryAgain
|
217
219
|
end
|
218
220
|
else
|
221
|
+
Log.warn "Non-recoverable error in #{job.path}"
|
219
222
|
next
|
220
223
|
end
|
221
224
|
ensure
|
@@ -253,7 +256,7 @@ module Workflow
|
|
253
256
|
end
|
254
257
|
end
|
255
258
|
|
256
|
-
def self.produce_dependencies(jobs, tasks, produce_cpus = Etc.nprocessors)
|
259
|
+
def self.produce_dependencies(jobs, tasks, produce_cpus = Etc.nprocessors, produce_timer = 5)
|
257
260
|
jobs = [jobs] unless Array === jobs
|
258
261
|
produce_list = []
|
259
262
|
jobs.each do |job|
|
@@ -265,7 +268,7 @@ module Workflow
|
|
265
268
|
end
|
266
269
|
end
|
267
270
|
|
268
|
-
orchestrator = Orchestrator.new
|
271
|
+
orchestrator = Orchestrator.new produce_timer, cpus: produce_cpus.to_i
|
269
272
|
orchestrator.process({}, produce_list)
|
270
273
|
produce_list
|
271
274
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
class TaskNotFound < StandardError; end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Path
|
2
|
+
def self.step_file?(path)
|
3
|
+
return false unless path =~ /\.files(?:\/|$)/
|
4
|
+
parts = path.split("/")
|
5
|
+
job = parts.select{|p| p =~ /\.files$/}.first
|
6
|
+
|
7
|
+
if job
|
8
|
+
i = parts.index job
|
9
|
+
begin
|
10
|
+
workflow, task = parts.values_at i - 2, i - 1
|
11
|
+
_loaded = false
|
12
|
+
begin
|
13
|
+
Kernel.const_get(workflow)
|
14
|
+
rescue
|
15
|
+
if ! _loaded
|
16
|
+
Workflow.require_workflow workflow
|
17
|
+
_loaded = true
|
18
|
+
retry
|
19
|
+
end
|
20
|
+
raise $!
|
21
|
+
end
|
22
|
+
return parts[i-2..-1] * "/"
|
23
|
+
rescue
|
24
|
+
Log.exception $!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
alias original_digest_str digest_str
|
32
|
+
|
33
|
+
def digest_str
|
34
|
+
if step_file = Path.step_file?(self)
|
35
|
+
"Step file: #{step_file}"
|
36
|
+
else
|
37
|
+
original_digest_str
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,20 +1,26 @@
|
|
1
1
|
class Step
|
2
2
|
def rec_dependencies(connected = false, seen = [])
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
@rec_dependencies = {}
|
4
|
+
@rec_dependencies[connected] ||= begin
|
5
|
+
direct_deps = []
|
6
|
+
dependencies.each do |dep|
|
7
|
+
next if seen.include? dep.path
|
8
|
+
next if connected && dep.done? && dep.updated?
|
9
|
+
direct_deps << dep
|
10
|
+
end if dependencies
|
11
|
+
seen.concat direct_deps.collect{|d| d.path }
|
12
|
+
seen.uniq!
|
13
|
+
direct_deps.inject(direct_deps){|acc,d| acc.concat(d.rec_dependencies(connected, seen)); acc }
|
14
|
+
direct_deps.uniq!
|
15
|
+
direct_deps
|
16
|
+
end
|
11
17
|
end
|
12
18
|
|
13
19
|
def recursive_inputs
|
14
|
-
recursive_inputs = NamedArray ===
|
20
|
+
recursive_inputs = NamedArray === inputs ? inputs.to_hash : {}
|
15
21
|
return recursive_inputs if dependencies.nil?
|
16
22
|
dependencies.inject(recursive_inputs) do |acc,dep|
|
17
|
-
acc.merge(
|
23
|
+
acc = dep.recursive_inputs.merge(acc)
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
@@ -41,6 +47,7 @@ class Step
|
|
41
47
|
end
|
42
48
|
|
43
49
|
next if dep.done?
|
50
|
+
next if dep.error? && ! dep.recoverable_error?
|
44
51
|
|
45
52
|
if dep.dependencies
|
46
53
|
dep.dependencies.each do |d|
|
@@ -72,9 +79,13 @@ class Step
|
|
72
79
|
def run_dependencies
|
73
80
|
all_dependencies.each do |dep|
|
74
81
|
next if dep.running? || dep.done?
|
82
|
+
next if dep.error? && ! dep.recoverable_error?
|
83
|
+
|
75
84
|
compute_options = compute[dep.path] if compute
|
76
85
|
compute_options = [] if compute_options.nil?
|
77
86
|
|
87
|
+
next if compute_options.include?(false)
|
88
|
+
|
78
89
|
stream = compute_options.include?(:stream)
|
79
90
|
stream = true unless ENV["SCOUT_EXPLICIT_STREAMING"] == 'true'
|
80
91
|
stream = :no_load if compute_options.include?(:produce)
|
@@ -95,12 +106,25 @@ class Step
|
|
95
106
|
all_dependencies.each{|dep| dep.abort if dep.running? }
|
96
107
|
end
|
97
108
|
|
98
|
-
def self.wait_for_jobs(jobs)
|
109
|
+
def self.wait_for_jobs(jobs, canfail=false)
|
99
110
|
threads = []
|
100
111
|
jobs.each do |job|
|
101
112
|
threads << Thread.new do
|
102
113
|
Thread.current.report_on_exception = false
|
103
|
-
|
114
|
+
begin
|
115
|
+
job.join
|
116
|
+
rescue Exception
|
117
|
+
case canfail
|
118
|
+
when TrueClass
|
119
|
+
next
|
120
|
+
else
|
121
|
+
if canfail === $!
|
122
|
+
next
|
123
|
+
else
|
124
|
+
raise $!
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
104
128
|
end
|
105
129
|
end
|
106
130
|
threads.each do |t|
|
@@ -7,6 +7,7 @@ class Step
|
|
7
7
|
else
|
8
8
|
Path.setup(dir)
|
9
9
|
end
|
10
|
+
dir = dir.find
|
10
11
|
dir.pkgdir = self
|
11
12
|
dir
|
12
13
|
end
|
@@ -34,7 +35,7 @@ class Step
|
|
34
35
|
begin
|
35
36
|
realpath = Open.realpath(self.files_dir)
|
36
37
|
Open.rm self.files_dir
|
37
|
-
Open.
|
38
|
+
Open.link_dir realpath, self.files_dir
|
38
39
|
rescue
|
39
40
|
Log.warn "Copy files_dir for #{self.workflow_short_path} failed: " + $!.message
|
40
41
|
end
|
@@ -10,7 +10,11 @@ class Step
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.load_info(info_file)
|
13
|
-
info =
|
13
|
+
info = begin
|
14
|
+
Persist.load(info_file, SERIALIZER) || {}
|
15
|
+
rescue
|
16
|
+
{status: :noinfo}
|
17
|
+
end
|
14
18
|
IndiferentHash.setup(info)
|
15
19
|
end
|
16
20
|
|
@@ -20,7 +24,7 @@ class Step
|
|
20
24
|
end
|
21
25
|
|
22
26
|
def save_info(info = nil)
|
23
|
-
Persist.save(info, info_file, SERIALIZER)
|
27
|
+
Persist.save(@info = info, info_file, SERIALIZER)
|
24
28
|
@info_load_time = Time.now
|
25
29
|
end
|
26
30
|
|
@@ -117,6 +121,7 @@ class Step
|
|
117
121
|
if message.nil?
|
118
122
|
Log.info [Log.color(:status, status, true), Log.color(:task, task_name, true), Log.color(:path, path)] * " "
|
119
123
|
else
|
124
|
+
message = Log.fingerprint(message).sub(/^'/,'').sub(/'$/,'')
|
120
125
|
Log.info [Log.color(:status, status, true), Log.color(:task, task_name, true), message, Log.color(:path, path)] * " "
|
121
126
|
end
|
122
127
|
end
|
@@ -139,6 +144,10 @@ class Step
|
|
139
144
|
info[:messages]
|
140
145
|
end
|
141
146
|
|
147
|
+
def message(message)
|
148
|
+
merge_info :message => message
|
149
|
+
end
|
150
|
+
|
142
151
|
def status
|
143
152
|
info[:status].tap{|s| s.nil? ? s : s.to_sym }
|
144
153
|
end
|
@@ -152,7 +161,7 @@ class Step
|
|
152
161
|
end
|
153
162
|
|
154
163
|
def running?
|
155
|
-
! done? && (info[:pid] && Misc.pid_alive?(info[:pid]))
|
164
|
+
! (done? && status == :done) && (info[:pid] && Misc.pid_alive?(info[:pid]))
|
156
165
|
end
|
157
166
|
|
158
167
|
def overriden?
|
@@ -161,7 +170,14 @@ class Step
|
|
161
170
|
end
|
162
171
|
|
163
172
|
def overriden_deps
|
164
|
-
|
173
|
+
dependencies.select{|d| d.overriden? }
|
174
|
+
end
|
175
|
+
|
176
|
+
def recursive_overriden_deps
|
177
|
+
overriden_deps = dependencies.select{|d|
|
178
|
+
d.overriden?
|
179
|
+
}
|
180
|
+
(overriden_deps + overriden_deps.collect{|d| d.recursive_overriden_deps }).flatten.uniq
|
165
181
|
end
|
166
182
|
|
167
183
|
def exception
|
@@ -4,9 +4,11 @@ class Step
|
|
4
4
|
Path.setup(path) unless Path === path
|
5
5
|
relocated = path.relocate
|
6
6
|
return relocated if Open.exists?(relocated)
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
if path.scan("/").length >= 2
|
8
|
+
subpath = path.split("/")[-3..-1] * "/"
|
9
|
+
relocated = Path.setup("var/jobs")[subpath]
|
10
|
+
return relocated if Open.exists?(relocated)
|
11
|
+
end
|
10
12
|
path
|
11
13
|
end
|
12
14
|
|
@@ -19,5 +19,11 @@ class Step
|
|
19
19
|
bar
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
def traverse(obj, desc: nil , **kwargs, &block)
|
24
|
+
desc = "Processing #{self.short_path}" if desc.nil?
|
25
|
+
kwargs[:bar] = self.progress_bar(desc) unless kwargs.include?(:bar)
|
26
|
+
TSV.traverse obj, **kwargs, &block
|
27
|
+
end
|
22
28
|
end
|
23
29
|
|
@@ -20,17 +20,24 @@ class Step
|
|
20
20
|
self.error? && ! (ScoutException === self.exception)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
return false if self.error? && self.recoverable_error?
|
25
|
-
return true if self.done? && ! ENV["SCOUT_UPDATE"]
|
23
|
+
def newer_dependencies
|
26
24
|
newer = rec_dependencies.select{|dep| Path.newer?(self.path, dep.path) }
|
27
25
|
newer += input_dependencies.select{|dep| Path.newer?(self.path, dep.path) }
|
26
|
+
newer += rec_dependencies.collect{|dep| dep.input_dependencies }.flatten.select{|dep| Path.newer?(self.path, dep.path) }
|
27
|
+
newer
|
28
|
+
end
|
29
|
+
|
30
|
+
def updated?
|
31
|
+
return false if self.error? && self.recoverable_error?
|
32
|
+
return true if (self.done? || (self.error? && ! self.recoverable_error?)) && ! ENV["SCOUT_UPDATE"]
|
33
|
+
newer = newer_dependencies
|
28
34
|
|
29
35
|
Log.low "Newer deps found for #{Log.fingerprint self}: #{Log.fingerprint newer}" if newer.any?
|
30
36
|
newer.empty?
|
31
37
|
end
|
32
38
|
|
33
39
|
def clean
|
40
|
+
Log.debug "Cleaning job files: #{path}"
|
34
41
|
@take_stream = nil
|
35
42
|
@result = nil
|
36
43
|
@info = nil
|
@@ -55,7 +62,7 @@ class Step
|
|
55
62
|
end
|
56
63
|
|
57
64
|
def canfail?
|
58
|
-
@compute && @compute.include?(:canfail)
|
65
|
+
@compute && @compute[self.path] && @compute[self.path].include?(:canfail)
|
59
66
|
end
|
60
67
|
|
61
68
|
def started?
|