rbbt-util 5.27.5 → 5.27.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/fix_width_table.rb +6 -5
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +2 -2
- data/lib/rbbt/resource/path.rb +3 -3
- data/lib/rbbt/util/misc/exceptions.rb +8 -0
- data/lib/rbbt/workflow/definition.rb +6 -0
- data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +9 -3
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +9 -3
- data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +7 -1
- data/lib/rbbt/workflow/step/accessor.rb +4 -0
- data/lib/rbbt/workflow/step/dependencies.rb +10 -6
- data/lib/rbbt/workflow/step/run.rb +1 -1
- data/lib/rbbt/workflow/task.rb +1 -1
- data/share/rbbt_commands/system/status +3 -2
- data/share/rbbt_commands/workflow/monitor +3 -3
- data/test/rbbt/workflow/step/test_dependencies.rb +40 -8
- data/test/rbbt/workflow/test_remote_workflow.rb +13 -1
- 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: fe7c3dec4d2333e77ea396a2d6e572512bf7033999ff4715f1a1c6c9d3d1b9d5
|
4
|
+
data.tar.gz: 32a3d905c1a95f9c7e5cb359855f8781509cfeecdd8db7b77ee29eaea528d030
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d009024642898f775d423e1ddede6aea538e8ed5ff4675eedadd64768e67b0a46f6519038378a221db76b0e196cfc713ca8dc7553788cdb9a51014c14a97de4c
|
7
|
+
data.tar.gz: 5c0612feca84b00e6d402f7a68ca1cebd6f4b7a785b40899bdaed3385a3f68853824dcc98d9cfd2e641768ef5ca3d52e38e41bdbc1d7a3751ae288e8f8d7ed2d
|
data/lib/rbbt/fix_width_table.rb
CHANGED
@@ -4,20 +4,21 @@ class FixWidthTable
|
|
4
4
|
def initialize(filename, value_size = nil, range = nil, update = false, in_memory = true)
|
5
5
|
@filename = filename
|
6
6
|
|
7
|
-
if update
|
7
|
+
if update || %w(memory stringio).include?(filename.to_s.downcase) || ! File.exist?(filename)
|
8
8
|
Log.debug "FixWidthTable create: #{ filename }"
|
9
9
|
@value_size = value_size
|
10
10
|
@range = range
|
11
11
|
@record_size = @value_size + (@range ? 16 : 8)
|
12
12
|
@write = true
|
13
13
|
|
14
|
-
if %w(memory stringio).include?
|
14
|
+
if %w(memory stringio).include?(filename.to_s.downcase)
|
15
15
|
@filename = :memory
|
16
16
|
@file = StringIO.new
|
17
17
|
else
|
18
18
|
FileUtils.rm @filename if File.exist? @filename
|
19
19
|
FileUtils.mkdir_p File.dirname(@filename) unless File.exist? @filename
|
20
|
-
|
20
|
+
#@file = File.open(@filename, 'wb')
|
21
|
+
@file = File.open(@filename, 'w:ASCII-8BIT')
|
21
22
|
end
|
22
23
|
|
23
24
|
@file.write [value_size].pack("L")
|
@@ -25,9 +26,9 @@ class FixWidthTable
|
|
25
26
|
|
26
27
|
@size = 0
|
27
28
|
else
|
28
|
-
Log.debug "FixWidthTable up-to-date: #{ filename }"
|
29
|
+
Log.debug "FixWidthTable up-to-date: #{ filename } - (in_memory:#{in_memory})"
|
29
30
|
if in_memory
|
30
|
-
@file =
|
31
|
+
@file = Open.open(@filename, :mode => 'r:ASCII-ASCII'){|f| StringIO.new f.read}
|
31
32
|
else
|
32
33
|
@file = File.open(@filename, 'r:ASCII-8BIT')
|
33
34
|
end
|
@@ -16,7 +16,7 @@ module Persist
|
|
16
16
|
end
|
17
17
|
|
18
18
|
dir = File.dirname(File.expand_path(path))
|
19
|
-
|
19
|
+
File.mkdir(dir) unless File.exists?(dir)
|
20
20
|
|
21
21
|
tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
|
22
22
|
tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
|
@@ -87,7 +87,7 @@ module Persist
|
|
87
87
|
def self.open_tokyocabinet(path, write, serializer = nil, tokyocabinet_class = TokyoCabinet::HDB)
|
88
88
|
write = true unless File.exist? path
|
89
89
|
|
90
|
-
FileUtils.mkdir_p File.dirname(path) unless
|
90
|
+
FileUtils.mkdir_p File.dirname(path) unless File.exist?(File.dirname(path))
|
91
91
|
|
92
92
|
database = Persist::TCAdapter.open(path, write, tokyocabinet_class)
|
93
93
|
|
data/lib/rbbt/resource/path.rb
CHANGED
@@ -199,7 +199,7 @@ module Path
|
|
199
199
|
next if res
|
200
200
|
next unless paths.include? w
|
201
201
|
path = find(w, caller_lib, paths)
|
202
|
-
res = path if File.exist?
|
202
|
+
res = path if File.exist?(path)
|
203
203
|
end if res.nil?
|
204
204
|
|
205
205
|
(paths.keys - STANDARD_SEARCH - search_order).each do |w|
|
@@ -241,8 +241,8 @@ module Path
|
|
241
241
|
sub('{REMOVE}/', '').
|
242
242
|
sub('{REMOVE}', '')
|
243
243
|
|
244
|
-
path = path + '.gz' if File.exist?
|
245
|
-
path = path + '.bgz' if File.exist?
|
244
|
+
path = path + '.gz' if File.exist?(path + '.gz')
|
245
|
+
path = path + '.bgz' if File.exist?(path + '.bgz')
|
246
246
|
|
247
247
|
self.annotate path
|
248
248
|
|
@@ -15,6 +15,14 @@ end
|
|
15
15
|
class Aborted < StandardError; end
|
16
16
|
|
17
17
|
class TryAgain < StandardError; end
|
18
|
+
|
19
|
+
class TryThis < StandardError
|
20
|
+
attr_accessor :payload
|
21
|
+
def initialize(payload = nil)
|
22
|
+
@payload = payload
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
18
26
|
class SemaphoreInterrupted < TryAgain; end
|
19
27
|
class LockInterrupted < TryAgain; end
|
20
28
|
|
@@ -18,6 +18,7 @@ module Workflow
|
|
18
18
|
:description => "",
|
19
19
|
:result_type => nil,
|
20
20
|
:result_description => "",
|
21
|
+
:resumable => false,
|
21
22
|
:extension => nil)
|
22
23
|
|
23
24
|
|
@@ -33,6 +34,10 @@ module Workflow
|
|
33
34
|
@extension = extension
|
34
35
|
end
|
35
36
|
|
37
|
+
def resumable
|
38
|
+
@resumable = true
|
39
|
+
end
|
40
|
+
|
36
41
|
def returns(description)
|
37
42
|
@result_description = description
|
38
43
|
end
|
@@ -118,6 +123,7 @@ module Workflow
|
|
118
123
|
:input_descriptions => consume_input_descriptions,
|
119
124
|
:required_inputs => consume_required_inputs,
|
120
125
|
:extension => consume_extension,
|
126
|
+
:resumable => consume_resumable,
|
121
127
|
:input_options => consume_input_options
|
122
128
|
}
|
123
129
|
|
@@ -137,13 +137,15 @@ class RemoteWorkflow
|
|
137
137
|
|
138
138
|
post_thread = Thread.new(Thread.current) do |parent|
|
139
139
|
bl = lambda do |rok|
|
140
|
-
if Net::HTTPOK === rok
|
140
|
+
if Net::HTTPOK === rok
|
141
141
|
_url = rok["RBBT-STREAMING-JOB-URL"]
|
142
142
|
@url = File.join(task_url, File.basename(_url)) if _url
|
143
143
|
rok.read_body do |c,_a, _b|
|
144
144
|
sin.write c
|
145
145
|
end
|
146
146
|
sin.close
|
147
|
+
elsif Net::HTTPSeeOther === rok
|
148
|
+
raise TryThis.new(rok)
|
147
149
|
else
|
148
150
|
err = StringIO.new
|
149
151
|
rok.read_body do |c,_a, _b|
|
@@ -156,7 +158,7 @@ class RemoteWorkflow
|
|
156
158
|
err.rewind
|
157
159
|
err.read
|
158
160
|
end
|
159
|
-
ne =
|
161
|
+
ne = RemoteWorkflow.parse_exception text
|
160
162
|
case ne
|
161
163
|
when String
|
162
164
|
parent.raise e.class, ne
|
@@ -173,7 +175,11 @@ class RemoteWorkflow
|
|
173
175
|
end
|
174
176
|
|
175
177
|
Log.debug{ "RestClient execute: #{ task_url } - #{Misc.fingerprint task_params}" }
|
176
|
-
|
178
|
+
begin
|
179
|
+
RestClient::Request.execute(:method => :post, :url => task_url, :payload => task_params, :block_response => bl)
|
180
|
+
rescue TryThis
|
181
|
+
RestClient::Request.execute(:method => :get, :url => $!.payload.header[:location], :block_response => bl)
|
182
|
+
end
|
177
183
|
end
|
178
184
|
|
179
185
|
# It seems like now response body are now decoded by Net::HTTP after 2.1
|
@@ -25,8 +25,13 @@ class RemoteStep < Step
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def cache_file
|
28
|
-
|
29
|
-
|
28
|
+
begin
|
29
|
+
digest = Misc.obj2digest([base_url, task, base_name, inputs])
|
30
|
+
Rbbt.var.cache.REST[[task, clean_name, digest].compact * "."].find
|
31
|
+
rescue
|
32
|
+
Log.exception $!
|
33
|
+
raise $!
|
34
|
+
end
|
30
35
|
end
|
31
36
|
|
32
37
|
def cache_files
|
@@ -62,7 +67,6 @@ class RemoteStep < Step
|
|
62
67
|
no_load ? Misc.add_GET_param(path, "_format", "raw") : @result
|
63
68
|
end
|
64
69
|
|
65
|
-
|
66
70
|
def self.get_streams(inputs, stream_input = nil)
|
67
71
|
new_inputs = {}
|
68
72
|
inputs.each do |k,v|
|
@@ -240,6 +244,7 @@ class RemoteStep < Step
|
|
240
244
|
return true if cache_files.any?
|
241
245
|
init_job unless @url
|
242
246
|
Log.debug{ "Joining RemoteStep: #{path}" }
|
247
|
+
|
243
248
|
if IO === @result
|
244
249
|
res = @result
|
245
250
|
@result = nil
|
@@ -253,6 +258,7 @@ class RemoteStep < Step
|
|
253
258
|
sleep 1 unless self.done? || self.aborted? || self.error?
|
254
259
|
while not (self.done? || self.aborted? || self.error?)
|
255
260
|
sleep 3
|
261
|
+
iif [self.done?, self.status, self.info]
|
256
262
|
end
|
257
263
|
end
|
258
264
|
|
@@ -129,7 +129,7 @@ class RemoteStep
|
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
-
def _run_job(cache_type = :
|
132
|
+
def _run_job(cache_type = :asynchronous)
|
133
133
|
get_streams
|
134
134
|
|
135
135
|
task_url = URI.encode(File.join(base_url, task.to_s))
|
@@ -142,7 +142,13 @@ class RemoteStep
|
|
142
142
|
else
|
143
143
|
@adaptor.execute_job(base_url, task, task_params, cache_type)
|
144
144
|
end
|
145
|
+
end
|
146
|
+
|
145
147
|
|
148
|
+
def produce(*args)
|
149
|
+
@started = true
|
150
|
+
_run_job
|
146
151
|
end
|
152
|
+
|
147
153
|
end
|
148
154
|
end
|
@@ -92,7 +92,7 @@ class Step
|
|
92
92
|
(job.done? && job.dirty?) || (job.error? && job.dirty?) ||
|
93
93
|
(!(job.noinfo? || job.done? || job.error? || job.aborted? || job.running?))
|
94
94
|
|
95
|
-
job.clean
|
95
|
+
job.clean unless job.resumable? && (job.updated? && ! job.dirty?)
|
96
96
|
job.set_info :status, :cleaned
|
97
97
|
end
|
98
98
|
|
@@ -144,14 +144,18 @@ class Step
|
|
144
144
|
|
145
145
|
dependency.status_lock.synchronize do
|
146
146
|
if dependency.aborted? || (dependency.error? && dependency.recoverable_error? && ! canfail_paths.include?(dependency.path) && ! already_failed.include?(dependency.path)) || (!Open.remote?(dependency.path) && dependency.missing?)
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
147
|
+
if dependency.resumable?
|
148
|
+
dependency.status = :resume
|
149
|
+
else
|
150
|
+
Log.warn "Cleaning dep. on exec #{Log.color :blue, dependency.path} (missing: #{dependency.missing?}; error #{dependency.error?})"
|
151
|
+
dependency.clean
|
152
|
+
already_failed << dependency.path
|
153
|
+
raise TryAgain
|
154
|
+
end
|
151
155
|
end
|
152
156
|
end
|
153
157
|
|
154
|
-
if ! (dependency.started? || dependency.error?)
|
158
|
+
if dependency.status == :resume || ! (dependency.started? || dependency.error?)
|
155
159
|
log_dependency_exec(dependency, :starting)
|
156
160
|
dependency.run(true)
|
157
161
|
raise TryAgain
|
data/lib/rbbt/workflow/task.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rbbt/util/misc'
|
|
2
2
|
require 'rbbt/persist'
|
3
3
|
|
4
4
|
module Task
|
5
|
-
attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :input_options, :required_inputs, :description, :name, :result_description, :extension, :workflow
|
5
|
+
attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :input_options, :required_inputs, :description, :name, :result_description, :extension, :workflow, :resumable
|
6
6
|
|
7
7
|
def self.setup(options = {}, &block)
|
8
8
|
block.extend Task
|
@@ -187,7 +187,7 @@ workflows.sort.each do |workflow,tasks|
|
|
187
187
|
if info_fields and info_fields.any?
|
188
188
|
info = begin
|
189
189
|
Open.open(i[:info_file]) do |f|
|
190
|
-
Step::
|
190
|
+
Step::INFO_SERIALIZER.load(f)
|
191
191
|
end
|
192
192
|
rescue
|
193
193
|
{:status => :noinfo}
|
@@ -198,9 +198,10 @@ workflows.sort.each do |workflow,tasks|
|
|
198
198
|
else
|
199
199
|
info = begin
|
200
200
|
Open.open(i[:info_file]) do |f|
|
201
|
-
Step::
|
201
|
+
Step::INFO_SERIALIZER.load(f)
|
202
202
|
end
|
203
203
|
rescue
|
204
|
+
Log.exception $!
|
204
205
|
{:status => :noinfo}
|
205
206
|
end
|
206
207
|
IndiferentHash.setup(info)
|
@@ -41,7 +41,7 @@ def list_jobs(options)
|
|
41
41
|
clean_file = file.sub('.info','')
|
42
42
|
begin
|
43
43
|
next if File.exist? clean_file and $quick
|
44
|
-
info = Step::
|
44
|
+
info = Step::INFO_SERIALIZER.load(Open.read(file, :mode => 'rb'))
|
45
45
|
next if (File.exist?(clean_file) or info[:status] == :done) and (info[:children_pids].nil? or info[:children_done] or info[:children_pids].select{|pid| Misc.pid_exists? pid}.empty?)
|
46
46
|
rescue Exception
|
47
47
|
puts "Error parsing info file: #{ file }"
|
@@ -86,7 +86,7 @@ def clean_jobs(options)
|
|
86
86
|
info = nil
|
87
87
|
next if File.exist? clean_file
|
88
88
|
begin
|
89
|
-
info = Step::
|
89
|
+
info = Step::INFO_SERIALIZER.load(Open.read(file, :mode => 'rb'))
|
90
90
|
rescue Exception
|
91
91
|
Log.debug "Error process #{ file }"
|
92
92
|
remove_job file if options[:errors]
|
@@ -117,7 +117,7 @@ begin
|
|
117
117
|
end
|
118
118
|
else
|
119
119
|
if options[:file]
|
120
|
-
info = Step::
|
120
|
+
info = Step::INFO_SERIALIZER.load(Open.read(options[:file], :mode => 'rb'))
|
121
121
|
print_job options[:file], info
|
122
122
|
else
|
123
123
|
list_jobs options
|
@@ -40,8 +40,8 @@ module DepWorkflow
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
dep :task2
|
44
43
|
dep :task5
|
44
|
+
dep :task2
|
45
45
|
task :task6 => :array do
|
46
46
|
s1 = TSV.get_stream step(:task2)
|
47
47
|
s2 = TSV.get_stream step(:task5)
|
@@ -81,6 +81,26 @@ module ComputeWorkflow
|
|
81
81
|
|
82
82
|
end
|
83
83
|
|
84
|
+
module ResumeWorkflow
|
85
|
+
extend Workflow
|
86
|
+
|
87
|
+
resumable
|
88
|
+
task :resume => :string do
|
89
|
+
if file('foo').exists?
|
90
|
+
'done'
|
91
|
+
else
|
92
|
+
Open.mkdir files_dir
|
93
|
+
Open.touch(file('foo'))
|
94
|
+
raise
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
dep :resume
|
99
|
+
task :reverse => :string do
|
100
|
+
step(:resume).load.reverse
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
84
104
|
class TestWorkflowDependency < Test::Unit::TestCase
|
85
105
|
def test_task1
|
86
106
|
size = 10000
|
@@ -152,13 +172,14 @@ class TestWorkflowDependency < Test::Unit::TestCase
|
|
152
172
|
Log.severity = 0
|
153
173
|
TmpFile.with_file(content) do |input_file|
|
154
174
|
begin
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
175
|
+
job = DepWorkflow.job(:task6, "TEST", :input_file => input_file)
|
176
|
+
job.recursive_clean
|
177
|
+
job.run(:stream)
|
178
|
+
io = TSV.get_stream job
|
179
|
+
while line = io.gets
|
180
|
+
last_line = line.strip
|
181
|
+
end
|
182
|
+
io.join
|
162
183
|
rescue Exception
|
163
184
|
job.abort
|
164
185
|
raise $!
|
@@ -204,5 +225,16 @@ class TestWorkflowDependency < Test::Unit::TestCase
|
|
204
225
|
assert_equal "Line #{size}\tTask1\tTask2", last_line
|
205
226
|
end
|
206
227
|
end
|
228
|
+
|
229
|
+
def test_resume
|
230
|
+
Log.severity = 0
|
231
|
+
job = ResumeWorkflow.job(:reverse)
|
232
|
+
job.recursive_clean
|
233
|
+
assert_raise do
|
234
|
+
job.run
|
235
|
+
end
|
236
|
+
assert job.dependencies.first.file('foo').exists?
|
237
|
+
assert_equal 'done'.reverse, job.run
|
238
|
+
end
|
207
239
|
end
|
208
240
|
|
@@ -61,6 +61,18 @@ class TestRemoteWorkflow < Test::Unit::TestCase
|
|
61
61
|
def test_rest
|
62
62
|
Log.with_severity 0 do
|
63
63
|
|
64
|
+
remote_workflow_server(TestWFRest) do |client|
|
65
|
+
job = client.job(:hi, nil, {})
|
66
|
+
job.clean
|
67
|
+
job = client.job(:hi, nil, {})
|
68
|
+
assert ! job.done?
|
69
|
+
job.run
|
70
|
+
job.produce
|
71
|
+
job = client.job(:hi, nil, {})
|
72
|
+
assert job.done?
|
73
|
+
sleep 1
|
74
|
+
end
|
75
|
+
|
64
76
|
remote_workflow_server(TestWFRest) do |client|
|
65
77
|
assert_equal "Hello World", client.job(:hi, nil, {}).run.chomp
|
66
78
|
assert_equal "Hello Miguel", client.job(:hi, nil, {:name => :Miguel}).run.chomp
|
@@ -78,7 +90,7 @@ class TestRemoteWorkflow < Test::Unit::TestCase
|
|
78
90
|
|
79
91
|
def _test_ssh
|
80
92
|
Log.severity = 0
|
81
|
-
client = RemoteWorkflow.new "ssh
|
93
|
+
client = RemoteWorkflow.new "ssh://#{ENV["HOSTNAME"]}:Translation", "Translation"
|
82
94
|
job = client.job("translate", "SSH-TEST-1", :genes => ["TP53","KRAS"])
|
83
95
|
assert_equal 2, job.run.select{|l| l =~ /ENSG/}.length
|
84
96
|
end
|
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.27.
|
4
|
+
version: 5.27.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|