rbbt-util 5.33.0 → 5.33.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a6b198e57fe73c0e36e7aea6164bafd1a8a97d10b3a992f17d0ba6dc531a3c7
4
- data.tar.gz: 5aa8b8753fc88d5de6fa8f6db31b9b71a57ee5dcc86380041582a4985984f749
3
+ metadata.gz: 3ffb05883cf1e7eda628395b50967322b42240ace100fb73a2f4c4a1ed5e8d27
4
+ data.tar.gz: 8b25c002f68b88dc0ba1f09c041258ee0ca15d4fc6f8dc3df5de37ea2473d059
5
5
  SHA512:
6
- metadata.gz: a61b6e6671803d73b7993b2de9c6cf16d4f463ddd04f9378b54c77a00eb7292b4e817eea14cce81704fe3f2640d38ede202a3928d293ab1fe7e0e67fa87a35b0
7
- data.tar.gz: d41b1477aab34bfc08610602a3e333a5701edb58d9fa10ecf24436659c4e996bb000ceccb20bbcba1f153ec4e888264ae47ab28689b9e2879601da0b7822e831
6
+ metadata.gz: 7b74e527336830eecb1cad52bb13cbcb335c734a18e9261d87cfba6da93422cf94a826e97d43c6ef1d37d122623408230d80a037a9a91000fa95a6cf9c818cf6
7
+ data.tar.gz: 8b8de5c12aac8dfae5f68018cb5aae4023b78993fa78aa7cf93cacc16eea4c2b959f75190ead6862502ecc75ae3ccd9cc462b1db26930943447a758f1f359cd9
@@ -11,7 +11,7 @@ module HPC
11
11
  iii :END_BATCHES
12
12
  else
13
13
  n = batch.dup
14
- n[:deps] = n[:deps].collect{|b| b[:top_level] }
14
+ n[:deps] = n[:deps].collect{|b| b[:top_level] } if n[:deps]
15
15
  iif n
16
16
  end
17
17
  end
@@ -79,7 +79,14 @@ module HPC
79
79
 
80
80
  batches.each do |batch|
81
81
  jobs = batch[:jobs]
82
- all_deps = jobs.collect{|d| job_dependencies(d) }.flatten.uniq
82
+ all_deps = jobs.collect{|d| job_dependencies(d) }.flatten.uniq - jobs
83
+
84
+ minimum = all_deps
85
+ all_deps.each do |dep|
86
+ minimum -= job_dependencies(dep)
87
+ end
88
+
89
+ all_deps = minimum
83
90
  deps = all_deps.collect do |d|
84
91
  (batches - [batch]).select{|batch| batch[:jobs].collect(&:path).include? d.path }
85
92
  end.flatten.uniq
@@ -14,8 +14,14 @@ module HPC
14
14
  options.delete "detach"
15
15
  options.delete "jobname"
16
16
 
17
- rules = YAML.load(Open.read(options[:orchestration_rules])) if options[:orchestration_rules]
18
- rules ||= {}
17
+ if options[:orchestration_rules]
18
+ rules = YAML.load(Open.read(options[:orchestration_rules]))
19
+ elsif Rbbt.etc.slurm["default.yaml"].exists?
20
+ rules = YAML.load(Open.read(Rbbt.etc.slurm["default.yaml"]))
21
+ else
22
+ rules = {}
23
+ end
24
+
19
25
  IndiferentHash.setup(rules)
20
26
 
21
27
  batches = HPC::Orchestration.job_batches(rules, job)
@@ -26,7 +32,29 @@ module HPC
26
32
  raise "No batch without unmet dependencies" if top.nil?
27
33
  batches.delete top
28
34
  job_options = options.merge(top[:rules])
29
- job_options.merge!(:batch_dependencies => top[:deps].nil? ? [] : top[:deps].collect{|d| batch_ids[d] })
35
+
36
+ if top[:deps].nil?
37
+ batch_dependencies = []
38
+ else
39
+ top_jobs = top[:jobs]
40
+
41
+ batch_dependencies = top[:deps].collect{|d|
42
+ target = d[:top_level]
43
+ canfail = false
44
+
45
+ top_jobs.each do |job|
46
+ canfail = true if job.canfail_paths.include?(target.path)
47
+ end
48
+
49
+ if canfail
50
+ 'canfail:' + batch_ids[d].to_s
51
+ else
52
+ batch_ids[d].to_s
53
+ end
54
+ }
55
+ end
56
+
57
+ job_options.merge!(:batch_dependencies => batch_dependencies )
30
58
  job_options.merge!(:manifest => top[:jobs].collect{|d| d.task_signature })
31
59
 
32
60
  if options[:dry_run]
data/lib/rbbt/util/cmd.rb CHANGED
@@ -75,7 +75,7 @@ module CMD
75
75
 
76
76
  string = ""
77
77
  options.each do |option, value|
78
- raise "Invalid option key: #{option.inspect}" if option.to_s !~ /^[a-z_0-9\-=]+$/i
78
+ raise "Invalid option key: #{option.inspect}" if option.to_s !~ /^[a-z_0-9\-=.]+$/i
79
79
  #raise "Invalid option value: #{value.inspect}" if value.to_s.include? "'"
80
80
  value = value.gsub("'","\\'") if value.to_s.include? "'"
81
81
 
@@ -32,8 +32,6 @@ class DependencyError < Aborted
32
32
  def initialize(msg)
33
33
  if defined? Step and Step === msg
34
34
  step = msg
35
- workflow = step.path.split("/")[-3]
36
- new_msg = [workflow, step.short_path, step.messages.last] * " - "
37
35
  new_msg = [step.path, step.messages.last] * ": "
38
36
  super(new_msg)
39
37
  else
@@ -42,6 +40,21 @@ class DependencyError < Aborted
42
40
  end
43
41
  end
44
42
 
43
+ class DependencyRbbtException < RbbtException
44
+ def initialize(msg)
45
+ if defined? Step and Step === msg
46
+ step = msg
47
+
48
+ new_msg = nil
49
+ new_msg = [step.path, step.messages.last] * ": "
50
+
51
+ super(new_msg)
52
+ else
53
+ super(msg)
54
+ end
55
+ end
56
+ end
57
+
45
58
  class DontClose < Exception; end
46
59
 
47
60
  class KeepLocked < Exception
@@ -64,4 +77,3 @@ class StopInsist < Exception
64
77
  @exception = exception
65
78
  end
66
79
  end
67
-
@@ -92,7 +92,12 @@ module Workflow
92
92
  self.dependencies = self.dependencies - [dep]
93
93
  Open.rm_rf self.files_dir if Open.exist? self.files_dir
94
94
  FileUtils.cp_r dep.files_dir, self.files_dir if Open.exist?(dep.files_dir)
95
- Open.ln_h dep.path, self.tmp_path
95
+
96
+ if dep.overriden
97
+ Open.link dep.path, self.tmp_path
98
+ else
99
+ Open.ln_h dep.path, self.tmp_path
100
+ end
96
101
 
97
102
  case remove.to_s
98
103
  when 'true'
@@ -4,7 +4,7 @@ module Workflow
4
4
  end
5
5
 
6
6
  def self.nextflow_includes(file)
7
- Open.read(file).scan(/^include\s*{\s*(.*?)(?:\s*as.*?)?}\s*from\s+"(.*?)"(?:\s*params.*)?/).collect{|p| p}.uniq
7
+ Open.read(file).scan(/^include\s*{\s*([^\s]*?)\s+.*?}\s*from\s+["'](.*?)["'](?:\s*params.*)?/).collect{|p| p}.uniq
8
8
  end
9
9
 
10
10
  def self.nextflow_recursive_params(file)
@@ -48,25 +48,43 @@ module Workflow
48
48
  task name => result do
49
49
  work = file('work')
50
50
  profile = config :profile, :nextflow
51
+ config_file = config :config, :nextflow
51
52
 
52
- new_inputs = inputs.zip(inputs.fields).collect do |v,f|
53
- if String === v && m = v.match(/^JOB_FILE:(.*)/)
54
- file(m[1])
55
- elsif v.nil?
56
- Rbbt::Config.get(['nextflow', f] * "_", 'default', f)
53
+ nextflow_inputs = {}
54
+
55
+ inputs.zip(inputs.fields).collect do |v,f|
56
+ v = if String === v && m = v.match(/^JOB_FILE:(.*)/)
57
+ file(m[1])
58
+ elsif v.nil?
59
+ Rbbt::Config.get(['nextflow', f] * "_", 'default', f)
60
+ else
61
+ v
62
+ end
63
+
64
+ if f.to_s.include?("-")
65
+ p,_sep, section = f.to_s.partition("-")
66
+ name = [section, p] * "."
57
67
  else
58
- v
68
+ name = f
59
69
  end
70
+
71
+ nextflow_inputs[name] = v
60
72
  end
61
73
 
62
- inputs.replace new_inputs
63
-
64
74
  Misc.in_dir file('stage') do
65
- if profile
66
- cmd("nextflow run -work-dir #{work} -ansi-log false -profile #{profile} #{file}", inputs.to_hash.merge('add_option_dashes' => true))
67
- else
68
- cmd("nextflow run -work-dir #{work} -ansi-log false #{file}", inputs.to_hash.merge('add_option_dashes' => true))
69
- end
75
+
76
+ cmd = "nextflow "
77
+
78
+ cmd += " -C #{config_file}" if config_file
79
+
80
+ cmd += " run"
81
+
82
+ cmd += " -work-dir #{work} -ansi-log false"
83
+
84
+ cmd += " -profile #{profile}" if profile
85
+
86
+
87
+ cmd("#{cmd} #{file}", nextflow_inputs.merge('add_option_dashes' => true))
70
88
  end
71
89
 
72
90
  output_file = file(output).glob.first if output
@@ -107,7 +107,26 @@ class Step
107
107
  canfail = ComputeDependency === job && job.canfail?
108
108
  end
109
109
 
110
- raise DependencyError, job if job.error? and not canfail
110
+ raise_dependency_error(job) if job.error? and not canfail
111
+ end
112
+
113
+ def self.raise_dependency_error(job)
114
+ begin
115
+ if job.get_exception
116
+ klass = job.get_exception.class
117
+ else
118
+ klass = Kernel.const_get(info[:exception][:class])
119
+ end
120
+ rescue
121
+ Log.exception $!
122
+ raise DependencyError, job
123
+ end
124
+
125
+ if (klass <= RbbtException)
126
+ raise DependencyRbbtException, job
127
+ else
128
+ raise DependencyError, job
129
+ end
111
130
  end
112
131
 
113
132
  def log_dependency_exec(dependency, action)
@@ -169,7 +188,7 @@ class Step
169
188
 
170
189
  if dependency.error?
171
190
  log_dependency_exec(dependency, :error)
172
- raise DependencyError, [dependency.path, dependency.messages.last] * ": " if dependency.error?
191
+ raise_dependency_error dependency
173
192
  end
174
193
 
175
194
  if dependency.streaming?
@@ -368,7 +387,7 @@ class Step
368
387
  seen_paths << step.path
369
388
  begin
370
389
  Step.prepare_for_execution(step) unless step == self
371
- rescue DependencyError
390
+ rescue DependencyError, DependencyRbbtException
372
391
  raise $! unless canfail_paths.include? step.path
373
392
  end
374
393
  next unless step.dependencies and step.dependencies.any?
@@ -493,6 +512,7 @@ class Step
493
512
  return true if @overriden
494
513
  return true if dependencies.select{|dep| dep.overriden? }.any?
495
514
  info[:archived_info].each do |f,i|
515
+ next if Symbol === i
496
516
  return true if i[:overriden] || i["overriden"]
497
517
  end if info[:archived_info]
498
518
  return false
@@ -285,7 +285,7 @@ class Step
285
285
  begin
286
286
  return true unless info[:exception]
287
287
  klass = Kernel.const_get(info[:exception][:class])
288
- ! (klass <= RbbtException)
288
+ ! (klass <= RbbtException )
289
289
  rescue Exception
290
290
  true
291
291
  end
@@ -437,7 +437,7 @@ class Step
437
437
  end
438
438
  end # END SYNC
439
439
  res
440
- rescue DependencyError
440
+ rescue DependencyError, DependencyRbbtException
441
441
  exception $!
442
442
  rescue LockInterrupted
443
443
  raise $!
@@ -484,7 +484,7 @@ class Step
484
484
  if dofork
485
485
  fork(true) unless started?
486
486
 
487
- join unless done?
487
+ join unless done? or dofork == :nowait
488
488
  else
489
489
  run(true) unless started?
490
490
 
@@ -496,6 +496,7 @@ class Step
496
496
 
497
497
  def fork(no_load = false, semaphore = nil)
498
498
  raise "Can not fork: Step is waiting for proces #{@pid} to finish" if not @pid.nil? and not Process.pid == @pid and Misc.pid_exists?(@pid) and not done? and info[:forked]
499
+ Log.debug "Fork to run #{self.path}"
499
500
  sout, sin = Misc.pipe if no_load == :stream
500
501
  @pid = Process.fork do
501
502
  Signal.trap(:TERM) do
@@ -71,6 +71,7 @@ module Workflow
71
71
 
72
72
  default_resources.each{|k,v| resources[k] ||= v } if default_resources
73
73
 
74
+ resources = {:cpus => 1} if resources.empty?
74
75
  resources
75
76
  end
76
77
 
@@ -83,7 +84,8 @@ module Workflow
83
84
 
84
85
  def self.candidates(workload, rules)
85
86
  if rules.empty?
86
- candidates = workload.select{|k,v| v.empty? }.
87
+ candidates = workload.
88
+ select{|k,v| v.empty? }.
87
89
  collect{|k,v| k }.
88
90
  reject{|k| k.done? }
89
91
  else
@@ -107,7 +109,8 @@ 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)
113
+ available_resources = {:cpus => Etc.nprocessors } if available_resources.nil?
111
114
  @timer = timer
112
115
  @available_resources = IndiferentHash.setup(available_resources)
113
116
  @resources_requested = IndiferentHash.setup({})
@@ -155,7 +158,7 @@ module Workflow
155
158
  log = job_rules[:log] if job_rules
156
159
  log = Log.severity if log.nil?
157
160
  Log.with_severity log do
158
- job.produce(false, true)
161
+ job.produce(false, :nowait)
159
162
  end
160
163
  end
161
164
  end
@@ -228,8 +231,9 @@ module Workflow
228
231
 
229
232
  new_workload = {}
230
233
  workload.each do |k,v|
231
- next if k.done?
232
- new_workload[k] = v.reject{|d| d.done? || (d.error? && ! d.recoverable_error?)}
234
+ next if k.done? || k.error? || k.aborted?
235
+ #new_workload[k] = v.reject{|d| d.done? || ((d.error? || d.aborted?) && ! d.recoverable_error?)}
236
+ new_workload[k] = v.reject{|d| d.done? || d.error? || d.aborted?}
233
237
  end
234
238
  workload = new_workload
235
239
  sleep timer
data/lib/rbbt/workflow.rb CHANGED
@@ -423,7 +423,7 @@ module Workflow
423
423
 
424
424
  # jobname => true sets the value of the input to the name of the job
425
425
  if task.input_options
426
- jobname_input = task.input_options.select{|i,o| o[:jobname]}.collect{|i,o| i }.first
426
+ jobname_input = task.input_options.select{|i,o| o[:jobname] }.collect{|i,o| i }.first
427
427
  else
428
428
  jobname_input = nil
429
429
  end
@@ -476,14 +476,14 @@ module Workflow
476
476
  end
477
477
  end
478
478
 
479
+ input_values = task.take_input_values(inputs)
479
480
  if real_inputs.empty? && Workflow::TAG != :inputs && ! overriden
480
481
  step_path = step_path taskname, jobname, [], [], extension
481
- input_values = task.take_input_values(inputs)
482
482
  else
483
- input_values = task.take_input_values(inputs)
484
483
  step_path = step_path taskname, jobname, input_values, dependencies, extension
485
484
  end
486
485
 
486
+
487
487
  job = get_job_step step_path, task, input_values, dependencies
488
488
  job.workflow = self
489
489
  job.clean_name = jobname
@@ -503,8 +503,6 @@ module Workflow
503
503
 
504
504
  def _job(taskname, jobname = nil, inputs = {})
505
505
 
506
- _inputs = IndiferentHash.setup(inputs.dup)
507
-
508
506
  task_info = task_info(taskname)
509
507
  task_inputs = task_info[:inputs]
510
508
  persist_inputs = inputs.values_at(*task_inputs)
@@ -191,7 +191,7 @@ The `recursive_clean` cleans all the job dependency steps recursively.
191
191
  -rcl--recursive_clean Clean the last step and its dependencies to recompute the job completely
192
192
  -uaj--update_all_jobs Consider all dependencies when checking for updates, even when they have no info files
193
193
  --fork Run job asyncronously and monitor progress. It monitors detached processes as well
194
- --orchestrate Run the job through the orchestrator
194
+ --orchestrate* Run the job through the orchestrator
195
195
  --detach Run job asyncronously and detach process
196
196
  --exec Run job with no persistence
197
197
  -O--output* Save job result into file
@@ -441,7 +441,17 @@ begin
441
441
  job.fork
442
442
  elsif options[:orchestrate]
443
443
  require 'rbbt/workflow/util/orchestrator'
444
- Workflow::Orchestrator.process job
444
+ rules = case options[:orchestrate]
445
+ when 'none', 'open', 'default'
446
+ nil
447
+ else
448
+ YAML.parse(Open.read(options[:orchestrate]))
449
+ end
450
+ if rules
451
+ Workflow::Orchestrator.process rules, job
452
+ else
453
+ Workflow::Orchestrator.process job
454
+ end unless job.done?
445
455
  else
446
456
  job.run(:stream)
447
457
  res = job
@@ -577,10 +587,10 @@ when Step
577
587
  elsif detach
578
588
  exit! 0
579
589
  else
590
+ res.join
580
591
  if %w(float integer string boolean).include?(res.result_type.to_s)
581
592
  out.puts res.load
582
593
  else
583
- res.join
584
594
  Open.open(res.path, :mode => 'rb') do |io|
585
595
  Misc.consume_stream(io, false, out)
586
596
  end if Open.exist?(res.path) || Open.remote?(res.path) || Open.ssh?(res.path)
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.0
4
+ version: 5.33.3
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-02-18 00:00:00.000000000 Z
11
+ date: 2022-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake