rbbt-util 5.44.1 → 6.0.4
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/LICENSE +1 -1
- data/bin/rbbt +67 -90
- data/bin/rbbt_exec.rb +2 -2
- data/etc/app.d/base.rb +2 -2
- data/etc/app.d/semaphores.rb +3 -3
- data/lib/rbbt/annotations/annotated_array.rb +207 -207
- data/lib/rbbt/annotations/refactor.rb +27 -0
- data/lib/rbbt/annotations/util.rb +282 -282
- data/lib/rbbt/annotations.rb +343 -320
- data/lib/rbbt/association/database.rb +200 -225
- data/lib/rbbt/association/index.rb +294 -291
- data/lib/rbbt/association/item.rb +227 -227
- data/lib/rbbt/association/open.rb +35 -34
- data/lib/rbbt/association/util.rb +0 -169
- data/lib/rbbt/association.rb +2 -4
- data/lib/rbbt/entity/identifiers.rb +119 -118
- data/lib/rbbt/entity/refactor.rb +12 -0
- data/lib/rbbt/entity.rb +319 -315
- data/lib/rbbt/hpc/batch.rb +72 -53
- data/lib/rbbt/hpc/lsf.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
- data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
- data/lib/rbbt/hpc/orchestrate.rb +19 -13
- data/lib/rbbt/hpc/slurm.rb +18 -18
- data/lib/rbbt/knowledge_base/entity.rb +13 -5
- data/lib/rbbt/knowledge_base/query.rb +2 -2
- data/lib/rbbt/knowledge_base/registry.rb +32 -31
- data/lib/rbbt/knowledge_base/traverse.rb +1 -1
- data/lib/rbbt/knowledge_base.rb +1 -1
- data/lib/rbbt/monitor.rb +36 -25
- data/lib/rbbt/persist/refactor.rb +166 -0
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
- data/lib/rbbt/persist/tsv.rb +187 -185
- data/lib/rbbt/persist.rb +556 -551
- data/lib/rbbt/refactor.rb +20 -0
- data/lib/rbbt/resource/path/refactor.rb +178 -0
- data/lib/rbbt/resource/path.rb +317 -497
- data/lib/rbbt/resource/util.rb +0 -48
- data/lib/rbbt/resource.rb +3 -390
- data/lib/rbbt/tsv/accessor.rb +2 -838
- data/lib/rbbt/tsv/attach.rb +303 -299
- data/lib/rbbt/tsv/change_id.rb +244 -245
- data/lib/rbbt/tsv/csv.rb +87 -85
- data/lib/rbbt/tsv/dumper.rb +2 -100
- data/lib/rbbt/tsv/excel.rb +26 -24
- data/lib/rbbt/tsv/field_index.rb +4 -1
- data/lib/rbbt/tsv/filter.rb +3 -2
- data/lib/rbbt/tsv/index.rb +2 -284
- data/lib/rbbt/tsv/manipulate.rb +750 -747
- data/lib/rbbt/tsv/marshal.rb +3 -3
- data/lib/rbbt/tsv/matrix.rb +2 -2
- data/lib/rbbt/tsv/parallel/through.rb +2 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
- data/lib/rbbt/tsv/parser.rb +678 -678
- data/lib/rbbt/tsv/refactor.rb +195 -0
- data/lib/rbbt/tsv/stream.rb +253 -251
- data/lib/rbbt/tsv/util.rb +420 -420
- data/lib/rbbt/tsv.rb +210 -208
- data/lib/rbbt/util/R/eval.rb +4 -4
- data/lib/rbbt/util/R/plot.rb +62 -166
- data/lib/rbbt/util/R.rb +21 -18
- data/lib/rbbt/util/cmd.rb +2 -318
- data/lib/rbbt/util/color.rb +269 -269
- data/lib/rbbt/util/colorize.rb +89 -89
- data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
- data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
- data/lib/rbbt/util/concurrency/processes.rb +389 -386
- data/lib/rbbt/util/config.rb +169 -167
- data/lib/rbbt/util/filecache.rb +1 -1
- data/lib/rbbt/util/iruby.rb +20 -0
- data/lib/rbbt/util/log/progress/report.rb +241 -241
- data/lib/rbbt/util/log/progress/util.rb +99 -99
- data/lib/rbbt/util/log/progress.rb +102 -102
- data/lib/rbbt/util/log/refactor.rb +49 -0
- data/lib/rbbt/util/log.rb +486 -532
- data/lib/rbbt/util/migrate.rb +2 -2
- data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
- data/lib/rbbt/util/misc/development.rb +12 -11
- data/lib/rbbt/util/misc/exceptions.rb +117 -112
- data/lib/rbbt/util/misc/format.rb +2 -230
- data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
- data/lib/rbbt/util/misc/inspect.rb +2 -476
- data/lib/rbbt/util/misc/lock.rb +109 -106
- data/lib/rbbt/util/misc/omics.rb +9 -1
- data/lib/rbbt/util/misc/pipes.rb +765 -793
- data/lib/rbbt/util/misc/refactor.rb +20 -0
- data/lib/rbbt/util/misc/ssw.rb +27 -17
- data/lib/rbbt/util/misc/system.rb +92 -105
- data/lib/rbbt/util/misc.rb +39 -20
- data/lib/rbbt/util/named_array/refactor.rb +4 -0
- data/lib/rbbt/util/named_array.rb +3 -220
- data/lib/rbbt/util/open/refactor.rb +7 -0
- data/lib/rbbt/util/open.rb +3 -857
- data/lib/rbbt/util/procpath.rb +6 -6
- data/lib/rbbt/util/python/paths.rb +27 -0
- data/lib/rbbt/util/python/run.rb +115 -0
- data/lib/rbbt/util/python/script.rb +110 -0
- data/lib/rbbt/util/python/util.rb +3 -3
- data/lib/rbbt/util/python.rb +22 -81
- data/lib/rbbt/util/semaphore.rb +152 -148
- data/lib/rbbt/util/simpleopt.rb +9 -8
- data/lib/rbbt/util/ssh/refactor.rb +19 -0
- data/lib/rbbt/util/ssh.rb +122 -118
- data/lib/rbbt/util/tar.rb +117 -115
- data/lib/rbbt/util/tmpfile.rb +69 -67
- data/lib/rbbt/util/version.rb +2 -0
- data/lib/rbbt/workflow/refactor/entity.rb +11 -0
- data/lib/rbbt/workflow/refactor/export.rb +66 -0
- data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
- data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
- data/lib/rbbt/workflow/refactor/task_info.rb +66 -0
- data/lib/rbbt/workflow/refactor.rb +150 -0
- data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +1 -2
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
- data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
- data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
- data/lib/rbbt/workflow/remote_workflow.rb +6 -1
- data/lib/rbbt/workflow/step/run.rb +766 -766
- data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
- data/lib/rbbt/workflow/step.rb +2 -362
- data/lib/rbbt/workflow/task.rb +118 -118
- data/lib/rbbt/workflow/usage.rb +289 -287
- data/lib/rbbt/workflow/util/archive.rb +6 -5
- data/lib/rbbt/workflow/util/data.rb +1 -1
- data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
- data/lib/rbbt/workflow/util/trace.rb +79 -44
- data/lib/rbbt/workflow.rb +4 -882
- data/lib/rbbt-util.rb +21 -13
- data/lib/rbbt.rb +16 -3
- data/python/rbbt/__init__.py +96 -4
- data/python/rbbt/workflow/remote.py +104 -0
- data/python/rbbt/workflow.py +64 -0
- data/python/test.py +10 -0
- data/share/Rlib/plot.R +37 -37
- data/share/Rlib/svg.R +22 -5
- data/share/install/software/lib/install_helpers +1 -1
- data/share/rbbt_commands/hpc/list +2 -3
- data/share/rbbt_commands/hpc/orchestrate +4 -4
- data/share/rbbt_commands/hpc/tail +2 -0
- data/share/rbbt_commands/hpc/task +10 -7
- data/share/rbbt_commands/lsf/list +2 -3
- data/share/rbbt_commands/lsf/orchestrate +4 -4
- data/share/rbbt_commands/lsf/tail +2 -0
- data/share/rbbt_commands/lsf/task +10 -7
- data/share/rbbt_commands/migrate +1 -1
- data/share/rbbt_commands/pbs/list +2 -3
- data/share/rbbt_commands/pbs/orchestrate +4 -4
- data/share/rbbt_commands/pbs/tail +2 -0
- data/share/rbbt_commands/pbs/task +10 -7
- data/share/rbbt_commands/resource/produce +8 -1
- data/share/rbbt_commands/slurm/list +2 -3
- data/share/rbbt_commands/slurm/orchestrate +4 -4
- data/share/rbbt_commands/slurm/tail +2 -0
- data/share/rbbt_commands/slurm/task +10 -7
- data/share/rbbt_commands/system/clean +5 -5
- data/share/rbbt_commands/system/status +5 -5
- data/share/rbbt_commands/tsv/get +2 -3
- data/share/rbbt_commands/tsv/info +10 -13
- data/share/rbbt_commands/tsv/keys +18 -14
- data/share/rbbt_commands/tsv/slice +2 -2
- data/share/rbbt_commands/tsv/transpose +6 -2
- data/share/rbbt_commands/workflow/info +20 -24
- data/share/rbbt_commands/workflow/list +1 -1
- data/share/rbbt_commands/workflow/prov +20 -13
- data/share/rbbt_commands/workflow/retry +43 -0
- data/share/rbbt_commands/workflow/server +12 -2
- data/share/rbbt_commands/workflow/task +80 -73
- data/share/rbbt_commands/workflow/write_info +26 -9
- data/share/software/opt/ssw/ssw.c +861 -0
- data/share/software/opt/ssw/ssw.h +130 -0
- data/share/workflow_config.ru +3 -3
- metadata +45 -6
data/lib/rbbt/workflow.rb
CHANGED
@@ -1,882 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require 'rbbt/workflow/accessor'
|
6
|
-
require 'rbbt/workflow/doc'
|
7
|
-
require 'rbbt/workflow/examples'
|
8
|
-
|
9
|
-
require 'rbbt/workflow/util/archive'
|
10
|
-
require 'rbbt/workflow/util/provenance'
|
11
|
-
|
12
|
-
module Workflow
|
13
|
-
|
14
|
-
class TaskNotFoundException < Exception
|
15
|
-
def initialize(workflow, task = nil)
|
16
|
-
if task
|
17
|
-
super "Task '#{ task }' not found in #{ workflow } workflow"
|
18
|
-
else
|
19
|
-
super workflow
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
#{{{ WORKFLOW MANAGEMENT
|
25
|
-
class << self
|
26
|
-
attr_accessor :workflows, :autoinstall, :workflow_dir, :main
|
27
|
-
end
|
28
|
-
|
29
|
-
self.workflows = []
|
30
|
-
|
31
|
-
def self.autoinstall
|
32
|
-
@autoload ||= ENV["RBBT_WORKFLOW_AUTOINSTALL"] == "true"
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.extended(base)
|
36
|
-
self.workflows << base
|
37
|
-
libdir = Path.caller_lib_dir
|
38
|
-
return if libdir.nil?
|
39
|
-
base.libdir = Path.setup(libdir).tap{|p| p.resource = base}
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.init_remote_tasks
|
43
|
-
return if defined? @@init_remote_tasks and @@init_remote_tasks
|
44
|
-
@@init_remote_tasks = true
|
45
|
-
load_remote_tasks(Rbbt.root.etc.remote_tasks.find) if Rbbt.root.etc.remote_tasks.exists?
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.init_relay_tasks
|
49
|
-
return if defined? @@init_relay_tasks and @@init_relay_tasks
|
50
|
-
@@init_relay_tasks = true
|
51
|
-
load_relay_tasks(Rbbt.root.etc.relay_tasks.find) if Rbbt.root.etc.relay_tasks.exists?
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
def self.require_remote_workflow(wf_name, url)
|
57
|
-
require 'rbbt/workflow/remote_workflow'
|
58
|
-
eval "Object::#{wf_name.split("+").first} = RemoteWorkflow.new '#{ url }', '#{wf_name}'"
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.load_workflow_libdir(filename)
|
62
|
-
workflow_lib_dir = File.join(File.dirname(File.expand_path(filename)), 'lib')
|
63
|
-
if File.directory? workflow_lib_dir
|
64
|
-
Log.debug "Adding workflow lib directory to LOAD_PATH: #{workflow_lib_dir}"
|
65
|
-
$LOAD_PATH.unshift(workflow_lib_dir)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.load_workflow_file(filename)
|
70
|
-
begin
|
71
|
-
|
72
|
-
load_workflow_libdir(filename)
|
73
|
-
|
74
|
-
filename = File.expand_path(filename)
|
75
|
-
|
76
|
-
Rbbt.add_version(filename)
|
77
|
-
|
78
|
-
require filename
|
79
|
-
Log.debug{"Workflow loaded from: #{ filename }"}
|
80
|
-
return true
|
81
|
-
rescue Exception
|
82
|
-
Log.warn{"Error loading workflow: #{ filename }"}
|
83
|
-
raise $!
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.installed_workflows
|
88
|
-
self.workflow_dir['**/workflow.rb'].glob_all.collect do |file|
|
89
|
-
File.basename(File.dirname(file))
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def self.workflow_dir
|
94
|
-
@workflow_dir ||= begin
|
95
|
-
case
|
96
|
-
when (defined?(Rbbt) and Rbbt.etc.workflow_dir.exists?)
|
97
|
-
dir = Rbbt.etc.workflow_dir.read.strip
|
98
|
-
dir = File.expand_path(dir)
|
99
|
-
Path.setup(dir)
|
100
|
-
when defined?(Rbbt)
|
101
|
-
Rbbt.workflows
|
102
|
-
else
|
103
|
-
dir = File.join(ENV['HOME'], '.workflows')
|
104
|
-
Path.setup(dir)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.local_workflow_filename(wf_name)
|
110
|
-
filename = nil
|
111
|
-
|
112
|
-
if Path === wf_name
|
113
|
-
case
|
114
|
-
# Points to workflow file
|
115
|
-
when ((File.exist?(wf_name.find) and not File.directory?(wf_name.find)) or File.exist?(wf_name.find + '.rb'))
|
116
|
-
filename = wf_name.find
|
117
|
-
|
118
|
-
# Points to workflow dir
|
119
|
-
when (File.exist?(wf_name.find) and File.directory?(wf_name.find) and File.exist?(File.join(wf_name.find, 'workflow.rb')))
|
120
|
-
filename = wf_name['workflow.rb'].find
|
121
|
-
end
|
122
|
-
|
123
|
-
else
|
124
|
-
if ((File.exist?(wf_name) and not File.directory?(wf_name)) or File.exist?(wf_name + '.rb'))
|
125
|
-
filename = (wf_name =~ /\.?\//) ? wf_name : "./" << wf_name
|
126
|
-
else
|
127
|
-
filename = workflow_dir[wf_name]['workflow.rb'].find
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
if filename.nil? or not File.exist?(filename)
|
132
|
-
wf_name_snake = Misc.snake_case(wf_name)
|
133
|
-
return local_workflow_filename(wf_name_snake) if wf_name_snake != wf_name
|
134
|
-
end
|
135
|
-
|
136
|
-
filename
|
137
|
-
end
|
138
|
-
|
139
|
-
def self.require_local_workflow(wf_name)
|
140
|
-
|
141
|
-
filename = local_workflow_filename(wf_name)
|
142
|
-
|
143
|
-
if filename and File.exist?(filename)
|
144
|
-
load_workflow_file filename
|
145
|
-
else
|
146
|
-
return false
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.require_workflow(wf_name, force_local=false)
|
151
|
-
Workflow.init_remote_tasks
|
152
|
-
Workflow.init_relay_tasks
|
153
|
-
# Already loaded
|
154
|
-
begin
|
155
|
-
workflow = Misc.string2const wf_name
|
156
|
-
Log.debug{"Workflow #{ wf_name } already loaded"}
|
157
|
-
return workflow
|
158
|
-
rescue Exception
|
159
|
-
end
|
160
|
-
|
161
|
-
# Load remotely
|
162
|
-
if not force_local and Rbbt.etc.remote_workflows.exists?
|
163
|
-
remote_workflows = Rbbt.etc.remote_workflows.yaml
|
164
|
-
if Hash === remote_workflows and remote_workflows.include?(wf_name)
|
165
|
-
url = remote_workflows[wf_name]
|
166
|
-
begin
|
167
|
-
return require_remote_workflow(wf_name, url)
|
168
|
-
ensure
|
169
|
-
Log.debug{"Workflow #{ wf_name } loaded remotely: #{ url }"}
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
if Open.remote?(wf_name) or Open.ssh?(wf_name)
|
175
|
-
url = wf_name
|
176
|
-
|
177
|
-
if Open.ssh?(wf_name)
|
178
|
-
wf_name = File.basename(url.split(":").last)
|
179
|
-
else
|
180
|
-
wf_name = File.basename(url)
|
181
|
-
end
|
182
|
-
|
183
|
-
begin
|
184
|
-
return require_remote_workflow(wf_name, url)
|
185
|
-
ensure
|
186
|
-
Log.debug{"Workflow #{ wf_name } loaded remotely: #{ url }"}
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
# Load locally
|
191
|
-
|
192
|
-
if wf_name =~ /::\w+$/
|
193
|
-
clean_name = wf_name.sub(/::.*/,'')
|
194
|
-
Log.info{"Looking for '#{wf_name}' in '#{clean_name}'"}
|
195
|
-
require_workflow clean_name
|
196
|
-
workflow = Misc.string2const Misc.camel_case(wf_name)
|
197
|
-
workflow.load_documentation
|
198
|
-
return workflow
|
199
|
-
end
|
200
|
-
|
201
|
-
Log.high{"Loading workflow #{wf_name}"}
|
202
|
-
|
203
|
-
first = nil
|
204
|
-
wf_name.split("+").each do |wf_name|
|
205
|
-
self.main = nil
|
206
|
-
require_local_workflow(wf_name) or
|
207
|
-
(Workflow.autoinstall and `rbbt workflow install #{Misc.snake_case(wf_name)} || rbbt workflow install #{wf_name}` and require_local_workflow(wf_name)) or raise("Workflow not found or could not be loaded: #{ wf_name }")
|
208
|
-
|
209
|
-
workflow = begin
|
210
|
-
Misc.string2const Misc.camel_case(wf_name)
|
211
|
-
rescue
|
212
|
-
self.main || Workflow.workflows.last
|
213
|
-
end
|
214
|
-
workflow.load_documentation
|
215
|
-
|
216
|
-
|
217
|
-
first ||= workflow
|
218
|
-
end
|
219
|
-
|
220
|
-
first.complete_name = wf_name
|
221
|
-
|
222
|
-
return first
|
223
|
-
end
|
224
|
-
|
225
|
-
attr_accessor :description
|
226
|
-
attr_accessor :libdir, :workdir
|
227
|
-
attr_accessor :helpers, :tasks
|
228
|
-
attr_accessor :task_dependencies, :task_description, :last_task
|
229
|
-
attr_accessor :stream_exports, :asynchronous_exports, :synchronous_exports, :exec_exports
|
230
|
-
attr_accessor :step_cache
|
231
|
-
attr_accessor :load_step_cache
|
232
|
-
attr_accessor :remote_tasks
|
233
|
-
attr_accessor :relay_tasks
|
234
|
-
|
235
|
-
#{{{ ATTR DEFAULTS
|
236
|
-
#
|
237
|
-
attr_accessor :complete_name
|
238
|
-
|
239
|
-
def self.complete_name
|
240
|
-
@complete_name ||= self.to_s
|
241
|
-
end
|
242
|
-
|
243
|
-
def self.workdir=(path)
|
244
|
-
path = Path.setup path.dup unless Path === path
|
245
|
-
@@workdir = path
|
246
|
-
end
|
247
|
-
|
248
|
-
def self.workdir
|
249
|
-
@@workdir ||= if defined? Rbbt
|
250
|
-
Rbbt.var.jobs
|
251
|
-
else
|
252
|
-
Path.setup('var/jobs')
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
TAG = ENV["RBBT_INPUT_JOBNAME"] == "true" ? :inputs : :hash
|
257
|
-
DEBUG_JOB_HASH = ENV["RBBT_DEBUG_JOB_HASH"] == 'true'
|
258
|
-
def step_path(taskname, jobname, inputs, dependencies, extension = nil)
|
259
|
-
raise "Jobname makes an invalid path: #{ jobname }" if jobname.include? '..'
|
260
|
-
if inputs.length > 0 or dependencies.any?
|
261
|
-
tagged_jobname = case TAG
|
262
|
-
when :hash
|
263
|
-
clean_inputs = Annotated.purge(inputs)
|
264
|
-
clean_inputs = clean_inputs.collect{|i| Symbol === i ? i.to_s : i }
|
265
|
-
deps_str = dependencies.collect{|d| (Step === d || (defined?(RemoteStep) && RemoteStep === d)) ? "Step: " << (Symbol === d.overriden ? d.path : d.short_path) : d }
|
266
|
-
key_obj = {:inputs => clean_inputs, :dependencies => deps_str }
|
267
|
-
key_str = Misc.obj2str(key_obj)
|
268
|
-
hash_str = Misc.digest(key_str)
|
269
|
-
Log.debug "Hash for '#{[taskname, jobname] * "/"}' #{hash_str} for #{key_str}" if DEBUG_JOB_HASH
|
270
|
-
jobname + '_' << hash_str
|
271
|
-
when :inputs
|
272
|
-
all_inputs = {}
|
273
|
-
inputs.zip(self.task_info(taskname)[:inputs]) do |i,f|
|
274
|
-
all_inputs[f] = i
|
275
|
-
end
|
276
|
-
dependencies.each do |dep|
|
277
|
-
ri = dep.recursive_inputs
|
278
|
-
ri.zip(ri.fields).each do |i,f|
|
279
|
-
all_inputs[f] = i
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
all_inputs.any? ? jobname + '_' << Misc.obj2str(all_inputs) : jobname
|
284
|
-
else
|
285
|
-
jobname
|
286
|
-
end
|
287
|
-
else
|
288
|
-
tagged_jobname = jobname
|
289
|
-
end
|
290
|
-
|
291
|
-
if extension and not extension.empty?
|
292
|
-
tagged_jobname = tagged_jobname + ('.' << extension.to_s)
|
293
|
-
end
|
294
|
-
|
295
|
-
workdir[taskname][tagged_jobname].find
|
296
|
-
end
|
297
|
-
|
298
|
-
def import_task(workflow, orig, new)
|
299
|
-
orig_task = workflow.tasks[orig]
|
300
|
-
new_task = orig_task.dup
|
301
|
-
options = {}
|
302
|
-
orig_task.singleton_methods.
|
303
|
-
select{|method| method.to_s[-1] != "="[0]}.each{|method|
|
304
|
-
if orig_task.respond_to?(method.to_s + "=")
|
305
|
-
options[method.to_s] = orig_task.send(method.to_s)
|
306
|
-
end
|
307
|
-
}
|
308
|
-
|
309
|
-
Task.setup(options, &new_task)
|
310
|
-
new_task.workflow = self
|
311
|
-
new_task.name = new
|
312
|
-
tasks[new] = new_task
|
313
|
-
task_dependencies[new] = workflow.task_dependencies[orig]
|
314
|
-
task_description[new] = workflow.task_description[orig]
|
315
|
-
end
|
316
|
-
|
317
|
-
def workdir=(path)
|
318
|
-
path = Path.setup path.dup unless Path === path
|
319
|
-
@workdir = path
|
320
|
-
end
|
321
|
-
|
322
|
-
def workdir
|
323
|
-
@workdir ||= begin
|
324
|
-
text = Module === self ? self.to_s : "Misc"
|
325
|
-
Workflow.workdir[text]
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
def libdir
|
330
|
-
@libdir = Path.setup(Path.caller_lib_dir) if @libdir.nil?
|
331
|
-
@libdir
|
332
|
-
end
|
333
|
-
|
334
|
-
def step_cache
|
335
|
-
Thread.current[:step_cache] ||= {}
|
336
|
-
end
|
337
|
-
|
338
|
-
def self.load_step_cache
|
339
|
-
Thread.current[:load_step_cache] ||= {}
|
340
|
-
end
|
341
|
-
|
342
|
-
|
343
|
-
def helpers
|
344
|
-
@helpers ||= {}
|
345
|
-
end
|
346
|
-
|
347
|
-
def tasks
|
348
|
-
@tasks ||= {}
|
349
|
-
end
|
350
|
-
|
351
|
-
def task_dependencies
|
352
|
-
@task_dependencies ||= {}
|
353
|
-
end
|
354
|
-
|
355
|
-
def task_description
|
356
|
-
@task_description ||= {}
|
357
|
-
end
|
358
|
-
|
359
|
-
def stream_exports
|
360
|
-
@stream_exports ||= []
|
361
|
-
end
|
362
|
-
|
363
|
-
def asynchronous_exports
|
364
|
-
@asynchronous_exports ||= []
|
365
|
-
end
|
366
|
-
|
367
|
-
def synchronous_exports
|
368
|
-
@synchronous_exports ||= []
|
369
|
-
end
|
370
|
-
|
371
|
-
def exec_exports
|
372
|
-
@exec_exports ||= []
|
373
|
-
end
|
374
|
-
|
375
|
-
def all_exports
|
376
|
-
@all_exports ||= asynchronous_exports + synchronous_exports + exec_exports + stream_exports
|
377
|
-
end
|
378
|
-
|
379
|
-
def documented_tasks
|
380
|
-
tasks.select{|k,v| v.description && ! v.description.empty? }.collect{|k,v| k }
|
381
|
-
end
|
382
|
-
|
383
|
-
# {{{ JOB MANAGEMENT
|
384
|
-
DEFAULT_NAME="Default"
|
385
|
-
|
386
|
-
def self.resolve_locals(inputs)
|
387
|
-
inputs.each do |name, value|
|
388
|
-
if (String === value and value =~ /^local:(.*?):(.*)/) or
|
389
|
-
(Array === value and value.length == 1 and value.first =~ /^local:(.*?):(.*)/) or
|
390
|
-
(TSV === value and value.size == 1 and value.keys.first =~ /^local:(.*?):(.*)/)
|
391
|
-
task_name = $1
|
392
|
-
jobname = $2
|
393
|
-
value = load_id(File.join(task_name, jobname)).load
|
394
|
-
inputs[name] = value
|
395
|
-
end
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def step_module
|
400
|
-
@_m ||= begin
|
401
|
-
m = Module.new
|
402
|
-
|
403
|
-
helpers.each do |name,block|
|
404
|
-
m.send(:define_method, name, &block)
|
405
|
-
end
|
406
|
-
|
407
|
-
m
|
408
|
-
end
|
409
|
-
@_m
|
410
|
-
end
|
411
|
-
|
412
|
-
def __job(taskname, jobname = nil, inputs = {})
|
413
|
-
taskname = taskname.to_sym
|
414
|
-
return remote_tasks[taskname].job(taskname, jobname, inputs) if remote_tasks and remote_tasks.include? taskname
|
415
|
-
|
416
|
-
task = tasks[taskname]
|
417
|
-
raise "Task not found: #{ taskname }" if task.nil?
|
418
|
-
|
419
|
-
inputs = IndiferentHash.setup(inputs)
|
420
|
-
|
421
|
-
not_overriden = inputs.delete :not_overriden
|
422
|
-
if not_overriden
|
423
|
-
inputs[:not_overriden] = :not_overriden_dep
|
424
|
-
end
|
425
|
-
|
426
|
-
Workflow.resolve_locals(inputs)
|
427
|
-
|
428
|
-
task_info = task_info(taskname)
|
429
|
-
task_inputs = task_info[:inputs]
|
430
|
-
#defaults = IndiferentHash.setup(task_info[:input_defaults]).merge(task.input_defaults)
|
431
|
-
all_defaults = IndiferentHash.setup(task_info[:input_defaults])
|
432
|
-
defaults = IndiferentHash.setup(task.input_defaults)
|
433
|
-
|
434
|
-
missing_inputs = []
|
435
|
-
task.required_inputs.each do |input|
|
436
|
-
missing_inputs << input if inputs[input].nil?
|
437
|
-
end if task.required_inputs
|
438
|
-
|
439
|
-
if missing_inputs.length == 1
|
440
|
-
raise ParameterException, "Input '#{missing_inputs.first}' is required but was not provided or is nil"
|
441
|
-
end
|
442
|
-
|
443
|
-
if missing_inputs.length > 1
|
444
|
-
raise ParameterException, "Inputs #{Misc.humanize_list(missing_inputs)} are required but were not provided or are nil"
|
445
|
-
end
|
446
|
-
|
447
|
-
# jobname => true sets the value of the input to the name of the job
|
448
|
-
if task.input_options
|
449
|
-
jobname_input = task.input_options.select{|i,o| o[:jobname] }.collect{|i,o| i }.first
|
450
|
-
else
|
451
|
-
jobname_input = nil
|
452
|
-
end
|
453
|
-
|
454
|
-
if jobname_input && inputs[jobname_input].nil?
|
455
|
-
inputs[jobname_input] = jobname || DEFAULT_NAME
|
456
|
-
end
|
457
|
-
|
458
|
-
real_inputs = {}
|
459
|
-
|
460
|
-
inputs.each do |k,v|
|
461
|
-
next unless (task_inputs.include?(k.to_sym) or task_inputs.include?(k.to_s))
|
462
|
-
default = all_defaults[k]
|
463
|
-
next if default == v
|
464
|
-
next if (String === default and Symbol === v and v.to_s == default)
|
465
|
-
next if (Symbol === default and String === v and v == default.to_s)
|
466
|
-
real_inputs[k.to_sym] = v
|
467
|
-
end
|
468
|
-
|
469
|
-
jobname_input_value = inputs[jobname_input] || all_defaults[jobname_input]
|
470
|
-
if jobname_input && jobname.nil? && String === jobname_input_value && ! jobname_input_value.include?('/')
|
471
|
-
jobname = jobname_input_value
|
472
|
-
end
|
473
|
-
|
474
|
-
jobname = DEFAULT_NAME if jobname.nil? or jobname.empty?
|
475
|
-
|
476
|
-
dependencies, overriden = real_dependencies(task, jobname, defaults.merge(inputs), task_dependencies[taskname] || [])
|
477
|
-
|
478
|
-
#overriden_deps = dependencies.select{|d| Symbol === d.overriden }
|
479
|
-
#overriden_target_deps = overriden_deps.select{|d| TrueClass === d.overriden }
|
480
|
-
|
481
|
-
extension = task.extension
|
482
|
-
|
483
|
-
if extension == :dep_task
|
484
|
-
extension = nil
|
485
|
-
if dependencies.any?
|
486
|
-
dep_basename = File.basename(dependencies.last.path)
|
487
|
-
if dep_basename.include? "."
|
488
|
-
parts = dep_basename.split(".")
|
489
|
-
extension = [parts.pop]
|
490
|
-
while parts.length > 1 && parts.last.length <= 4
|
491
|
-
extension << parts.pop
|
492
|
-
end
|
493
|
-
extension = extension.reverse * "."
|
494
|
-
end
|
495
|
-
end
|
496
|
-
end
|
497
|
-
|
498
|
-
#overriden = true if dependencies.select{|d| d.overriden && d.clean_name != d.name }.any?
|
499
|
-
overriden = true if ! not_overriden && dependencies.select{|d| Symbol === d.overriden }.any?
|
500
|
-
|
501
|
-
input_values = task.take_input_values(inputs)
|
502
|
-
if real_inputs.empty? && Workflow::TAG != :inputs && ! overriden #&& ! dependencies.select{|d| d.overriden && d.clean_name != d.name }.any?
|
503
|
-
step_path = step_path taskname, jobname, [], [], extension
|
504
|
-
else
|
505
|
-
step_path = step_path taskname, jobname, input_values, dependencies, extension
|
506
|
-
end
|
507
|
-
|
508
|
-
job = get_job_step step_path, task, input_values, dependencies
|
509
|
-
job.workflow = self
|
510
|
-
job.overriden = overriden if job.overriden.nil?
|
511
|
-
job.clean_name = jobname
|
512
|
-
|
513
|
-
#iif [job, not_overriden]
|
514
|
-
#case not_overriden
|
515
|
-
#when TrueClass
|
516
|
-
# job.overriden = false
|
517
|
-
#when :not_overriden_dep
|
518
|
-
# job.overriden = true if overriden_target_deps.any?
|
519
|
-
#else
|
520
|
-
# job.overriden = true if overriden_deps.any?
|
521
|
-
#end
|
522
|
-
|
523
|
-
job.real_inputs = real_inputs.keys
|
524
|
-
job
|
525
|
-
end
|
526
|
-
|
527
|
-
def _job(taskname, jobname = nil, inputs = {})
|
528
|
-
|
529
|
-
task_info = task_info(taskname)
|
530
|
-
task_inputs = task_info[:inputs]
|
531
|
-
persist_inputs = inputs.values_at(*task_inputs)
|
532
|
-
persist_inputs += inputs.values_at(*inputs.keys.select{|k| String === k && k.include?("#") }.sort)
|
533
|
-
Persist.memory("STEP", :workflow => self.to_s, :taskname => taskname, :jobname => jobname, :inputs => persist_inputs, :repo => step_cache) do
|
534
|
-
__job(taskname, jobname, inputs)
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
def job(taskname, jobname = nil, inputs = {})
|
539
|
-
inputs, jobname = jobname, nil if Hash === jobname
|
540
|
-
begin
|
541
|
-
_job(taskname, jobname, inputs)
|
542
|
-
ensure
|
543
|
-
step_cache.clear
|
544
|
-
end
|
545
|
-
end
|
546
|
-
|
547
|
-
|
548
|
-
def set_step_dependencies(step)
|
549
|
-
if step.info[:dependencies]
|
550
|
-
Misc.insist do
|
551
|
-
step.dependencies = step.info[:dependencies].collect do |task, job, path|
|
552
|
-
next if job.nil?
|
553
|
-
if Open.exists?(path)
|
554
|
-
load_step(path)
|
555
|
-
else
|
556
|
-
Workflow.load_step(path)
|
557
|
-
end
|
558
|
-
end
|
559
|
-
end
|
560
|
-
end
|
561
|
-
end
|
562
|
-
|
563
|
-
#{{{ LOAD FROM FILE
|
564
|
-
|
565
|
-
def get_job_step(step_path, task = nil, input_values = nil, dependencies = nil)
|
566
|
-
step_path = step_path.call if Proc === step_path
|
567
|
-
persist = input_values.nil? ? false : true
|
568
|
-
persist = false
|
569
|
-
|
570
|
-
if ! (Path === step_path ? step_path.find : File.exist?(step_path)) &&
|
571
|
-
step_path.split("/").length == 3 &&
|
572
|
-
File.exist?(new_path = Rbbt.var.jobs[step_path].find)
|
573
|
-
|
574
|
-
step_path = new_path
|
575
|
-
end
|
576
|
-
|
577
|
-
key = Path === step_path ? step_path.find : step_path
|
578
|
-
|
579
|
-
if ! File.exist?(step_path) && step_path.split("/").length == 3 && File.exist?(new_path = Rbbt.var.jobs[step_path].find)
|
580
|
-
step_path = new_path
|
581
|
-
end
|
582
|
-
|
583
|
-
step = Step.new step_path, task, input_values, dependencies
|
584
|
-
|
585
|
-
set_step_dependencies(step) unless dependencies
|
586
|
-
|
587
|
-
step.extend step_module
|
588
|
-
|
589
|
-
step.task ||= task
|
590
|
-
step.inputs ||= input_values
|
591
|
-
step.dependencies = dependencies if dependencies and (step.dependencies.nil? or step.dependencies.length < dependencies.length)
|
592
|
-
|
593
|
-
step
|
594
|
-
end
|
595
|
-
|
596
|
-
def load_step(path)
|
597
|
-
task = task_for path
|
598
|
-
if task
|
599
|
-
get_job_step path, tasks[task.to_sym]
|
600
|
-
else
|
601
|
-
get_job_step path
|
602
|
-
end
|
603
|
-
end
|
604
|
-
|
605
|
-
def self.transplant(listed, real, other)
|
606
|
-
if listed.nil?
|
607
|
-
parts = real.split("/")
|
608
|
-
other_parts = other.split("/")
|
609
|
-
listed = (other_parts[0..-4] + parts[-3..-1]) * "/"
|
610
|
-
end
|
611
|
-
|
612
|
-
sl = listed.split("/", -1)
|
613
|
-
so = other.split("/", -1)
|
614
|
-
sr = real.split("/", -1)
|
615
|
-
prefix = []
|
616
|
-
while true
|
617
|
-
break if sl[0] != so[0]
|
618
|
-
cl = sl.shift
|
619
|
-
co = so.shift
|
620
|
-
prefix << cl
|
621
|
-
end
|
622
|
-
File.join(sr - sl + so)
|
623
|
-
end
|
624
|
-
|
625
|
-
def self.relocate_array(real, list)
|
626
|
-
preal = real.split(/\/+/)
|
627
|
-
prefix = preal[0..-4] * "/"
|
628
|
-
list.collect do |other|
|
629
|
-
pother = other.split(/\/+/)
|
630
|
-
end_part = pother[-3..-1] * "/"
|
631
|
-
new_path = prefix + "/" << end_part
|
632
|
-
if File.exist? new_path
|
633
|
-
new_path
|
634
|
-
else
|
635
|
-
Rbbt.var.jobs[end_part].find
|
636
|
-
end
|
637
|
-
end
|
638
|
-
end
|
639
|
-
|
640
|
-
def self.relocate(real, other)
|
641
|
-
preal = real.split(/\/+/)
|
642
|
-
pother = other.split(/\/+/)
|
643
|
-
end_part = pother[-3..-1] * "/"
|
644
|
-
new_path = preal[0..-4] * "/" << "/" << end_part
|
645
|
-
return new_path if File.exist?(new_path) || File.exist?(new_path + '.info')
|
646
|
-
Rbbt.var.jobs[end_part].find
|
647
|
-
end
|
648
|
-
|
649
|
-
def self.relocate_dependency(main, dep)
|
650
|
-
dep_path = dep.path
|
651
|
-
path = main.path
|
652
|
-
if Open.exists?(dep_path) || Open.exists?(dep_path + '.info')
|
653
|
-
dep
|
654
|
-
else
|
655
|
-
new_path = relocate(path, dep_path)
|
656
|
-
relocated = true if Open.exists?(new_path) || Open.exists?(new_path + '.info')
|
657
|
-
Workflow._load_step new_path
|
658
|
-
end
|
659
|
-
end
|
660
|
-
|
661
|
-
def self.__load_step(path)
|
662
|
-
if Open.remote?(path) || Open.ssh?(path)
|
663
|
-
require 'rbbt/workflow/remote_workflow'
|
664
|
-
return RemoteWorkflow.load_path path
|
665
|
-
end
|
666
|
-
step = Step.new path
|
667
|
-
relocated = false
|
668
|
-
dependencies = (step.info[:dependencies] || []).collect do |task,name,dep_path|
|
669
|
-
dep_path = task if dep_path.nil?
|
670
|
-
if Open.exists?(dep_path) || Open.exists?(dep_path + '.info') || Open.remote?(dep_path) || Open.ssh?(dep_path)
|
671
|
-
Workflow._load_step dep_path
|
672
|
-
else
|
673
|
-
new_path = relocate(path, dep_path)
|
674
|
-
relocated = true if Open.exists?(new_path) || Open.exists?(new_path + '.info')
|
675
|
-
Workflow._load_step new_path
|
676
|
-
end
|
677
|
-
end
|
678
|
-
step.instance_variable_set("@dependencies", dependencies)
|
679
|
-
step.relocated = relocated
|
680
|
-
step.load_inputs_from_info
|
681
|
-
step
|
682
|
-
end
|
683
|
-
|
684
|
-
def self.fast_load_step(path)
|
685
|
-
if Open.remote?(path) || Open.ssh?(path)
|
686
|
-
require 'rbbt/workflow/remote_workflow'
|
687
|
-
return RemoteWorkflow.load_path path
|
688
|
-
end
|
689
|
-
|
690
|
-
step = Step.new path
|
691
|
-
step.dependencies = nil
|
692
|
-
class << step
|
693
|
-
def dependencies
|
694
|
-
@dependencies ||= (self.info[:dependencies] || []).collect do |task,name,dep_path|
|
695
|
-
dep = if Open.exists?(dep_path) || Open.exists?(dep_path + '.info')
|
696
|
-
relocate = false
|
697
|
-
Workflow.fast_load_step dep_path
|
698
|
-
else
|
699
|
-
new_path = Workflow.relocate(path, dep_path)
|
700
|
-
relocated = true if Open.exists?(new_path) || Open.exists?(new_path + '.info')
|
701
|
-
Workflow.fast_load_step new_path
|
702
|
-
end
|
703
|
-
dep.relocated = relocated
|
704
|
-
dep
|
705
|
-
end
|
706
|
-
@dependencies
|
707
|
-
end
|
708
|
-
|
709
|
-
def inputs
|
710
|
-
self.load_inputs_from_info unless @inputs
|
711
|
-
@inputs
|
712
|
-
end
|
713
|
-
|
714
|
-
def dirty?
|
715
|
-
false
|
716
|
-
end
|
717
|
-
|
718
|
-
def updated?
|
719
|
-
true
|
720
|
-
end
|
721
|
-
end
|
722
|
-
|
723
|
-
if ! Open.exists?(step.info_file)
|
724
|
-
begin
|
725
|
-
workflow = step.path.split("/")[-3]
|
726
|
-
task_name = step.path.split("/")[-2]
|
727
|
-
workflow = Kernel.const_get workflow
|
728
|
-
step.task = workflow.tasks[task_name.to_sym]
|
729
|
-
rescue
|
730
|
-
Log.exception $!
|
731
|
-
end
|
732
|
-
end
|
733
|
-
step
|
734
|
-
end
|
735
|
-
|
736
|
-
def self._load_step(path)
|
737
|
-
Persist.memory("STEP", :path => path, :repo => load_step_cache) do
|
738
|
-
__load_step(path)
|
739
|
-
end
|
740
|
-
end
|
741
|
-
|
742
|
-
def self.load_step(path)
|
743
|
-
path = Path.setup(path.dup) unless Path === path
|
744
|
-
|
745
|
-
if ! (Path === path ? path.exists? : File.exist?(path)) && path.split("/").length == 3
|
746
|
-
new_path = Rbbt.var.jobs[path]
|
747
|
-
if new_path.exists? || new_path.set_extension('info').exists?
|
748
|
-
path = new_path
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
path = path.find if Path === path
|
753
|
-
|
754
|
-
begin
|
755
|
-
_load_step(path)
|
756
|
-
ensure
|
757
|
-
load_step_cache.clear
|
758
|
-
end
|
759
|
-
end
|
760
|
-
|
761
|
-
def load_id(id)
|
762
|
-
path = if Path === workdir
|
763
|
-
workdir[id].find
|
764
|
-
else
|
765
|
-
File.join(workdir, id)
|
766
|
-
end
|
767
|
-
task = task_for path
|
768
|
-
return remote_tasks[task].load_id(id) if remote_tasks && remote_tasks.include?(task)
|
769
|
-
return Workflow.load_step path
|
770
|
-
end
|
771
|
-
|
772
|
-
|
773
|
-
def fast_load_id(id)
|
774
|
-
path = if Path === workdir
|
775
|
-
workdir[id].find
|
776
|
-
else
|
777
|
-
File.join(workdir, id)
|
778
|
-
end
|
779
|
-
task = task_for path
|
780
|
-
return remote_tasks[task].load_id(id) if remote_tasks && remote_tasks.include?(task)
|
781
|
-
return Workflow.fast_load_step path
|
782
|
-
end
|
783
|
-
|
784
|
-
def load_name(task, name)
|
785
|
-
return remote_tasks[task].load_step(path) if remote_tasks and remote_tasks.include? task
|
786
|
-
task = tasks[task.to_sym] if String === task or Symbol === task
|
787
|
-
path = step_path task.name, name, [], [], task.extension
|
788
|
-
get_job_step path, task
|
789
|
-
end
|
790
|
-
|
791
|
-
#}}} LOAD FROM FILE
|
792
|
-
|
793
|
-
def jobs(taskname, query = nil)
|
794
|
-
task_dir = File.join(File.expand_path(workdir.find), taskname.to_s)
|
795
|
-
pattern = File.join(File.expand_path(task_dir), '**/*')
|
796
|
-
job_info_files = Dir.glob(Step.info_file(pattern)).collect{|f| Misc.path_relative_to task_dir, f }
|
797
|
-
job_info_files = job_info_files.select{|f| f.index(query) == 0 } if query
|
798
|
-
job_info_files.collect{|f|
|
799
|
-
job_name = Step.job_name_for_info_file(f, tasks[taskname].extension)
|
800
|
-
}
|
801
|
-
end
|
802
|
-
|
803
|
-
#{{{ Make workflow resources local
|
804
|
-
def local_persist_setup
|
805
|
-
class << self
|
806
|
-
include LocalPersist
|
807
|
-
end
|
808
|
-
self.local_persist_dir = Rbbt.var.cache.persistence.find :lib
|
809
|
-
end
|
810
|
-
|
811
|
-
def local_workdir_setup
|
812
|
-
self.workdir = Rbbt.var.jobs.find :lib
|
813
|
-
end
|
814
|
-
|
815
|
-
def make_local
|
816
|
-
local_persist_setup
|
817
|
-
local_workdir_setup
|
818
|
-
end
|
819
|
-
|
820
|
-
def with_workdir(workdir)
|
821
|
-
saved = self.workdir
|
822
|
-
begin
|
823
|
-
self.workdir = Path.setup(File.expand_path(workdir))
|
824
|
-
yield
|
825
|
-
ensure
|
826
|
-
self.workdir = saved
|
827
|
-
end
|
828
|
-
end
|
829
|
-
|
830
|
-
def add_remote_tasks(remote_tasks)
|
831
|
-
remote_tasks.each do |remote, tasks|
|
832
|
-
tasks.each do |task|
|
833
|
-
self.remote_tasks[task.to_f] = remote
|
834
|
-
end
|
835
|
-
end
|
836
|
-
end
|
837
|
-
|
838
|
-
def self.process_remote_tasks(remote_tasks)
|
839
|
-
require 'rbbt/workflow/remote_workflow'
|
840
|
-
remote_tasks.each do |workflow, info|
|
841
|
-
wf = Workflow.require_workflow workflow
|
842
|
-
wf.remote_tasks ||= {}
|
843
|
-
IndiferentHash.setup wf.remote_tasks
|
844
|
-
info.each do |remote, tasks|
|
845
|
-
remote_wf = RemoteWorkflow.new remote, workflow
|
846
|
-
tasks.each do |task|
|
847
|
-
Log.debug "Add remote task #{task} in #{wf} using #{remote_wf.url}"
|
848
|
-
wf.remote_tasks[task.to_sym] = remote_wf
|
849
|
-
end
|
850
|
-
end
|
851
|
-
end
|
852
|
-
end
|
853
|
-
|
854
|
-
def self.load_remote_tasks(filename)
|
855
|
-
remote_workflow_tasks = Misc.load_yaml(filename)
|
856
|
-
Workflow.process_remote_tasks(remote_workflow_tasks)
|
857
|
-
end
|
858
|
-
|
859
|
-
def self.process_relay_tasks(relay_tasks)
|
860
|
-
require 'rbbt/workflow/remote_workflow'
|
861
|
-
relay_tasks.each do |workflow, servers|
|
862
|
-
wf = Workflow.require_workflow workflow
|
863
|
-
wf.relay_tasks ||= {}
|
864
|
-
IndiferentHash.setup wf.relay_tasks
|
865
|
-
servers.each do |server, tasks|
|
866
|
-
case tasks
|
867
|
-
when Array
|
868
|
-
tasks.each do |task|
|
869
|
-
wf.relay_tasks[task.to_sym] = [server, {:migrate => :true}]
|
870
|
-
end
|
871
|
-
else
|
872
|
-
wf.relay_tasks[tasks.to_sym] = [server, {:migrate => :true}]
|
873
|
-
end
|
874
|
-
end
|
875
|
-
end
|
876
|
-
end
|
877
|
-
|
878
|
-
def self.load_relay_tasks(filename)
|
879
|
-
relay_workflow_tasks = Misc.load_yaml(filename)
|
880
|
-
Workflow.process_relay_tasks(relay_workflow_tasks)
|
881
|
-
end
|
882
|
-
end
|
1
|
+
require_relative 'util/misc/refactor'
|
2
|
+
Rbbt.require_instead 'scout/workflow'
|
3
|
+
require_relative 'workflow/refactor'
|
4
|
+
require_relative 'workflow/util/archive'
|