rbbt-util 5.20.26 → 5.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rbbt/annotations.rb +3 -1
- data/lib/rbbt/monitor.rb +12 -10
- data/lib/rbbt/persist.rb +1 -1
- data/lib/rbbt/rest/client.rb +2 -2
- data/lib/rbbt/rest/client/adaptor.rb +1 -0
- data/lib/rbbt/rest/client/get.rb +1 -33
- data/lib/rbbt/rest/client/run.rb +100 -0
- data/lib/rbbt/rest/client/step.rb +26 -73
- data/lib/rbbt/tsv/util.rb +7 -2
- data/lib/rbbt/util/log/progress/report.rb +1 -0
- data/lib/rbbt/util/misc/concurrent_stream.rb +6 -2
- data/lib/rbbt/util/misc/development.rb +18 -14
- data/lib/rbbt/util/misc/exceptions.rb +16 -7
- data/lib/rbbt/util/misc/inspect.rb +3 -2
- data/lib/rbbt/util/misc/pipes.rb +10 -7
- data/lib/rbbt/util/task/job.rb +6 -6
- data/lib/rbbt/workflow.rb +29 -2
- data/lib/rbbt/workflow/accessor.rb +14 -1
- data/lib/rbbt/workflow/definition.rb +23 -4
- data/lib/rbbt/workflow/soap.rb +1 -0
- data/lib/rbbt/workflow/step/dependencies.rb +5 -3
- data/lib/rbbt/workflow/step/run.rb +23 -5
- data/share/rbbt_commands/workflow/server +16 -3
- data/share/rbbt_commands/workflow/task +9 -0
- data/share/workflow_config.ru +35 -7
- data/test/rbbt/test_workflow.rb +24 -0
- data/test/rbbt/tsv/test_stream.rb +16 -0
- data/test/rbbt/util/misc/test_bgzf.rb +1 -1
- data/test/rbbt/util/test_misc.rb +29 -12
- metadata +64 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 752166bf720d5525c25bf96a2a01915c5ee7430c
|
4
|
+
data.tar.gz: 973d98ccede9449355b494982789b8cb82c325e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31ee0806440ed08fd319e7dfe9cbcd524ec7f40bbe10cfa8b56c411172d0e27d84397b8a64674000b6b340f433e79425fa8a779d640a802c3d835cc861e7df49
|
7
|
+
data.tar.gz: 7763048e9ee7786cb9270e9656b821093c5d67e2f2bdef8f1fc3448b11b0fa187fcf1f53a6918de4918a759bfec4ee4755b07313015efb6620895583cb4e9549
|
data/lib/rbbt/annotations.rb
CHANGED
@@ -69,7 +69,9 @@ module Annotated
|
|
69
69
|
def info(masked = false)
|
70
70
|
|
71
71
|
if @info.nil?
|
72
|
-
|
72
|
+
annotation_values = self.annotation_values
|
73
|
+
annotation_values = annotation_values.dup unless annotation_values.nil?
|
74
|
+
info = annotation_values
|
73
75
|
info[:annotation_types] = annotation_types
|
74
76
|
info[:annotated_array] = true if AnnotatedArray === self
|
75
77
|
@info = info
|
data/lib/rbbt/monitor.rb
CHANGED
@@ -10,16 +10,18 @@ module Rbbt
|
|
10
10
|
|
11
11
|
SENSIBLE_WRITE_DIRS = Misc.sensiblewrite_dir.find_all
|
12
12
|
|
13
|
-
PERSIST_DIRS = Rbbt.share.find_all + Rbbt.var.cache.persistence.find_all
|
13
|
+
PERSIST_DIRS = Rbbt.share.find_all + Rbbt.var.cache.persistence.find_all
|
14
14
|
|
15
15
|
JOB_DIRS = Rbbt.var.jobs.find_all
|
16
16
|
|
17
|
+
MUTEX_FOR_THREAD_EXCLUSIVE = Mutex.new
|
18
|
+
|
17
19
|
def self.dump_memory(file, obj = nil)
|
18
20
|
Log.info "Dumping #{obj} objects into #{ file }"
|
19
21
|
Thread.new do
|
20
22
|
while true
|
21
23
|
Open.write(file) do |f|
|
22
|
-
|
24
|
+
MUTEX_FOR_THREAD_EXCLUSIVE.synchronize do
|
23
25
|
GC.start
|
24
26
|
ObjectSpace.each_object(obj) do |o|
|
25
27
|
f.puts "---"
|
@@ -60,9 +62,9 @@ module Rbbt
|
|
60
62
|
lock_info[f] = {}
|
61
63
|
begin
|
62
64
|
lock_info[f].merge!(file_time(f))
|
63
|
-
if File.size(f) > 0
|
65
|
+
if File.size(f) > 0
|
64
66
|
info = Open.open(f) do |s|
|
65
|
-
YAML.load(s)
|
67
|
+
YAML.load(s)
|
66
68
|
end
|
67
69
|
IndiferentHash.setup(info)
|
68
70
|
lock_info[f][:pid] = info[:pid]
|
@@ -98,7 +100,7 @@ module Rbbt
|
|
98
100
|
end
|
99
101
|
|
100
102
|
# PERSISTS
|
101
|
-
|
103
|
+
|
102
104
|
def self.persists(dirs = PERSIST_DIRS)
|
103
105
|
dirs.collect do |dir|
|
104
106
|
next unless Open.exists? dir
|
@@ -145,7 +147,7 @@ module Rbbt
|
|
145
147
|
files = `find "#{ taskdir }/" -not -type d -not -path "*/*.files/*" 2>/dev/null`.split("\n").sort
|
146
148
|
_files = Set.new files
|
147
149
|
TSV.traverse files, :type => :array, :into => jobs do |file|
|
148
|
-
if m = file.match(/(.*).info$/)
|
150
|
+
if m = file.match(/(.*).(info|pid)$/)
|
149
151
|
file = m[1]
|
150
152
|
end
|
151
153
|
|
@@ -161,7 +163,7 @@ module Rbbt
|
|
161
163
|
if _files.include? file
|
162
164
|
info = info.merge(file_time(file))
|
163
165
|
info[:done] = true
|
164
|
-
info[:info_file] = File.
|
166
|
+
info[:info_file] = File.exist?(info_file) ? info_file : nil
|
165
167
|
else
|
166
168
|
info = info.merge({:info_file => info_file, :done => false})
|
167
169
|
end
|
@@ -200,7 +202,7 @@ module Rbbt
|
|
200
202
|
job = f.sub(/\.(info|files)/,'')
|
201
203
|
|
202
204
|
jobs[workflow][task][job] ||= {}
|
203
|
-
if jobs[workflow][task][job][:status].nil?
|
205
|
+
if jobs[workflow][task][job][:status].nil?
|
204
206
|
status = nil
|
205
207
|
status = :done if Open.exists? job
|
206
208
|
if status.nil? and f=~/\.info/
|
@@ -208,7 +210,7 @@ module Rbbt
|
|
208
210
|
Step::INFO_SERIALIAZER.load(Open.read(f, :mode => 'rb'))
|
209
211
|
rescue
|
210
212
|
{}
|
211
|
-
end
|
213
|
+
end
|
212
214
|
status = info[:status]
|
213
215
|
pid = info[:pid]
|
214
216
|
end
|
@@ -224,7 +226,7 @@ module Rbbt
|
|
224
226
|
|
225
227
|
def self.load_lock(lock)
|
226
228
|
begin
|
227
|
-
info = Misc.insist 3 do
|
229
|
+
info = Misc.insist 3 do
|
228
230
|
YAML.load(Open.read(lock))
|
229
231
|
end
|
230
232
|
info.values_at "pid", "ppid", "time"
|
data/lib/rbbt/persist.rb
CHANGED
data/lib/rbbt/rest/client.rb
CHANGED
@@ -11,7 +11,7 @@ require 'rbbt/rest/client/step'
|
|
11
11
|
class WorkflowRESTClient
|
12
12
|
include Workflow
|
13
13
|
|
14
|
-
attr_accessor :url, :name, :exec_exports, :asynchronous_exports, :
|
14
|
+
attr_accessor :url, :name, :exec_exports, :synchronous_exports, :asynchronous_exports, :stream_exports
|
15
15
|
|
16
16
|
def initialize(url, name)
|
17
17
|
Log.debug{ "Loading remote workflow #{ name }: #{ url }" }
|
@@ -45,7 +45,7 @@ class WorkflowRESTClient
|
|
45
45
|
|
46
46
|
|
47
47
|
stream_input = @can_stream ? task_info(task)[:input_options].select{|k,o| o[:stream] }.collect{|k,o| k }.first : nil
|
48
|
-
RemoteStep.new(url, task, name, fixed_inputs, task_info[:result_type], task_info[:result_description], @exec_exports.include?(task), stream_input)
|
48
|
+
RemoteStep.new(url, task, name, fixed_inputs, task_info[:result_type], task_info[:result_description], @exec_exports.include?(task), @stream_exports.include?(task), stream_input)
|
49
49
|
end
|
50
50
|
|
51
51
|
def load_id(id)
|
@@ -61,6 +61,7 @@ class WorkflowRESTClient
|
|
61
61
|
@asynchronous_exports = task_exports["asynchronous"].collect{|task| task.to_sym }
|
62
62
|
@synchronous_exports = task_exports["synchronous"].collect{|task| task.to_sym }
|
63
63
|
@exec_exports = task_exports["exec"].collect{|task| task.to_sym }
|
64
|
+
@stream_exports = task_exports["stream"].collect{|task| task.to_sym }
|
64
65
|
@can_stream = task_exports["can_stream"]
|
65
66
|
end
|
66
67
|
end
|
data/lib/rbbt/rest/client/get.rb
CHANGED
@@ -54,11 +54,11 @@ class WorkflowRESTClient
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def self.get_raw(url, params = {})
|
57
|
-
Log.debug{ "RestClient get_raw: #{ url } - #{Misc.fingerprint params}" }
|
58
57
|
params = params.merge({ :_format => 'raw' })
|
59
58
|
params = fix_params params
|
60
59
|
res = capture_exception do
|
61
60
|
Misc.insist(2, 0.5) do
|
61
|
+
Log.debug{ "RestClient get_raw: #{ url } - #{Misc.fingerprint params}" }
|
62
62
|
res = RestClient.get(URI.encode(url), :params => params)
|
63
63
|
raise TryAgain if res.code == 202
|
64
64
|
res
|
@@ -119,36 +119,4 @@ class WorkflowRESTClient
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
def self.stream_job(task_url, task_params, stream_input, cache_type = :exec)
|
123
|
-
require 'rbbt/util/misc/multipart_payload'
|
124
|
-
WorkflowRESTClient.capture_exception do
|
125
|
-
Log.debug{ "RestClient stream #{Process.pid}: #{ task_url } #{stream_input} #{cache_type} - #{Misc.fingerprint task_params}" }
|
126
|
-
res = RbbtMutiplartPayload.issue task_url, task_params, stream_input, nil, nil, true
|
127
|
-
type = res.gets
|
128
|
-
out = case type.strip
|
129
|
-
when "LOCATION"
|
130
|
-
@url = res.gets
|
131
|
-
@url.sub!(/\?.*/,'')
|
132
|
-
WorkflowRESTClient.get_raw(@url)
|
133
|
-
when /STREAM: (.*)/
|
134
|
-
@url = $1.strip
|
135
|
-
res.callback = Proc.new do
|
136
|
-
Log.medium "Done streaming result from #{@url}"
|
137
|
-
@done = true
|
138
|
-
end
|
139
|
-
res
|
140
|
-
when "BULK"
|
141
|
-
begin
|
142
|
-
res.read
|
143
|
-
ensure
|
144
|
-
@done = true
|
145
|
-
end
|
146
|
-
else
|
147
|
-
raise "What? " + type
|
148
|
-
end
|
149
|
-
ConcurrentStream.setup(out, :filename => @url)
|
150
|
-
out
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
122
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class WorkflowRESTClient::RemoteStep
|
2
|
+
|
3
|
+
def stream_job(task_url, task_params, stream_input, cache_type = :exec)
|
4
|
+
require 'rbbt/util/misc/multipart_payload'
|
5
|
+
WorkflowRESTClient.capture_exception do
|
6
|
+
@streaming = true
|
7
|
+
|
8
|
+
Log.debug{ "RestClient stream #{Process.pid}: #{ task_url } #{stream_input} #{cache_type} - #{Misc.fingerprint task_params}" }
|
9
|
+
res = RbbtMutiplartPayload.issue task_url, task_params, stream_input, nil, nil, true
|
10
|
+
type = res.gets
|
11
|
+
|
12
|
+
out = case type.strip
|
13
|
+
when "LOCATION"
|
14
|
+
@url = res.gets
|
15
|
+
@url.sub!(/\?.*/,'')
|
16
|
+
join
|
17
|
+
WorkflowRESTClient.get_raw(@url)
|
18
|
+
@done = true
|
19
|
+
@streaming = false
|
20
|
+
when /STREAM: (.*)/
|
21
|
+
@url = $1.strip
|
22
|
+
res.callback = Proc.new do
|
23
|
+
Log.medium "Done streaming result from #{@url}"
|
24
|
+
@done = true
|
25
|
+
@streaming = false
|
26
|
+
end
|
27
|
+
res
|
28
|
+
when "BULK"
|
29
|
+
begin
|
30
|
+
res.read
|
31
|
+
ensure
|
32
|
+
@done = true
|
33
|
+
@streaming = false
|
34
|
+
end
|
35
|
+
else
|
36
|
+
raise "What? " + type
|
37
|
+
end
|
38
|
+
|
39
|
+
ConcurrentStream.setup(out, :filename => @url)
|
40
|
+
|
41
|
+
out
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def execute_job(task_url, task_params, cache_type)
|
46
|
+
WorkflowRESTClient.capture_exception do
|
47
|
+
task_url = URI.encode(File.join(base_url, task.to_s))
|
48
|
+
|
49
|
+
sout, sin = Misc.pipe
|
50
|
+
|
51
|
+
post_thread = Thread.new(Thread.current) do |parent|
|
52
|
+
bl = lambda do |rok|
|
53
|
+
if Net::HTTPOK === rok
|
54
|
+
_url = rok["RBBT-STREAMING-JOB-URL"]
|
55
|
+
@url = File.join(task_url, File.basename(_url)) if _url
|
56
|
+
rok.read_body do |c,_a, _b|
|
57
|
+
sin.write c
|
58
|
+
end
|
59
|
+
sin.close
|
60
|
+
else
|
61
|
+
parent.raise "Error in RestClient: " << rok.message
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Log.debug{ "RestClient execute: #{ url } - #{Misc.fingerprint task_params}" }
|
66
|
+
RestClient::Request.execute(:method => :post, :url => task_url, :payload => task_params, :block_response => bl)
|
67
|
+
end
|
68
|
+
|
69
|
+
reader = Zlib::GzipReader.new(sout)
|
70
|
+
res_io = Misc.open_pipe do |sin|
|
71
|
+
while c = reader.read(Misc::BLOCK_SIZE)
|
72
|
+
sin.write c
|
73
|
+
end
|
74
|
+
sin.close
|
75
|
+
@done = true
|
76
|
+
end
|
77
|
+
|
78
|
+
ConcurrentStream.setup(res_io, :threads => [post_thread]) do
|
79
|
+
@done = true
|
80
|
+
@streaming = false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def _run_job(cache_type = :async)
|
86
|
+
get_streams
|
87
|
+
|
88
|
+
task_url = URI.encode(File.join(base_url, task.to_s))
|
89
|
+
WorkflowRESTClient.__prepare_inputs_for_restclient(inputs)
|
90
|
+
task_params = inputs.merge(:_cache_type => cache_type, :jobname => base_name, :_format => [:string, :boolean, :tsv, :annotations].include?(result_type) ? :raw : :json)
|
91
|
+
|
92
|
+
if cache_type == :stream or cache_type == :exec and stream_input and inputs[stream_input]
|
93
|
+
io = self.stream_job(task_url, task_params, stream_input, cache_type)
|
94
|
+
return io
|
95
|
+
else
|
96
|
+
execute_job(task_url, task_params, cache_type)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -18,22 +18,34 @@ class WorkflowRESTClient
|
|
18
18
|
|
19
19
|
class RemoteStep < Step
|
20
20
|
|
21
|
-
attr_accessor :url, :base_url, :task, :base_name, :inputs, :result_type, :result_description, :is_exec, :stream_input
|
21
|
+
attr_accessor :url, :base_url, :task, :base_name, :inputs, :result_type, :result_description, :is_exec, :is_stream, :stream_input
|
22
22
|
|
23
|
-
def initialize(base_url, task = nil, base_name = nil, inputs = nil, result_type = nil, result_description = nil, is_exec = false, stream_input = nil)
|
24
|
-
@base_url, @task, @base_name, @inputs, @result_type, @result_description, @is_exec, @stream_input = base_url, task, base_name, inputs, result_type, result_description, is_exec, stream_input
|
23
|
+
def initialize(base_url, task = nil, base_name = nil, inputs = nil, result_type = nil, result_description = nil, is_exec = false, is_stream = false, stream_input = nil)
|
24
|
+
@base_url, @task, @base_name, @inputs, @result_type, @result_description, @is_exec, @is_stream, @stream_input = base_url, task, base_name, inputs, result_type, result_description, is_exec, is_stream, stream_input
|
25
25
|
@mutex = Mutex.new
|
26
26
|
end
|
27
27
|
|
28
|
-
def run(
|
28
|
+
def run(no_load = false)
|
29
|
+
no_load = @is_stream ? :stream : true if no_load
|
30
|
+
|
29
31
|
@mutex.synchronize do
|
30
32
|
@result ||= begin
|
31
33
|
if @is_exec
|
32
|
-
exec(
|
33
|
-
elsif
|
34
|
+
exec(no_load)
|
35
|
+
elsif no_load == :stream
|
34
36
|
_run_job(:stream)
|
37
|
+
#init_job
|
38
|
+
#join
|
39
|
+
#Misc.open_pipe do |sin|
|
40
|
+
# body = get.body
|
41
|
+
# sin.write body
|
42
|
+
#end
|
43
|
+
elsif no_load
|
44
|
+
init_job
|
45
|
+
nil
|
35
46
|
else
|
36
47
|
init_job
|
48
|
+
join
|
37
49
|
self.load
|
38
50
|
end
|
39
51
|
ensure
|
@@ -41,8 +53,8 @@ class WorkflowRESTClient
|
|
41
53
|
end
|
42
54
|
end
|
43
55
|
|
44
|
-
return @result if
|
45
|
-
|
56
|
+
return @result if no_load == :stream
|
57
|
+
no_load ? path + '?_format=raw' : @result
|
46
58
|
end
|
47
59
|
|
48
60
|
|
@@ -79,7 +91,7 @@ class WorkflowRESTClient
|
|
79
91
|
end
|
80
92
|
|
81
93
|
def abort
|
82
|
-
|
94
|
+
WorkflowRESTClient.get_json(@url + '?_update=abort') if @url and @name
|
83
95
|
end
|
84
96
|
|
85
97
|
def name
|
@@ -99,7 +111,7 @@ class WorkflowRESTClient
|
|
99
111
|
end
|
100
112
|
|
101
113
|
def info(check_lock=false)
|
102
|
-
@done = @info
|
114
|
+
@done = @info && @info[:status] && @info[:status].to_sym == :done
|
103
115
|
@info = Persist.memory("RemoteSteps Info", :url => @url, :persist => !!@done) do
|
104
116
|
init_job unless @url
|
105
117
|
info = WorkflowRESTClient.get_json(File.join(@url, 'info'))
|
@@ -150,6 +162,7 @@ class WorkflowRESTClient
|
|
150
162
|
end
|
151
163
|
|
152
164
|
def grace
|
165
|
+
produce unless @started
|
153
166
|
sleep 0.1 unless started?
|
154
167
|
sleep 0.5 unless started?
|
155
168
|
sleep 1 unless started?
|
@@ -259,72 +272,10 @@ class WorkflowRESTClient
|
|
259
272
|
|
260
273
|
def load
|
261
274
|
params = {}
|
275
|
+
join unless done? or streaming?
|
262
276
|
load_res get
|
263
277
|
end
|
264
278
|
|
265
|
-
def _run_job(cache_type = :async)
|
266
|
-
get_streams
|
267
|
-
if cache_type == :stream or cache_type == :exec and stream_input and inputs[stream_input]
|
268
|
-
task_url = URI.encode(File.join(base_url, task.to_s))
|
269
|
-
WorkflowRESTClient.__prepare_inputs_for_restclient(inputs)
|
270
|
-
task_params = inputs.merge(:_cache_type => cache_type, :jobname => base_name, :_format => [:string, :boolean, :tsv, :annotations].include?(result_type) ? :raw : :json)
|
271
|
-
@streaming = true
|
272
|
-
io = WorkflowRESTClient.stream_job(task_url, task_params, stream_input, cache_type)
|
273
|
-
if IO === io
|
274
|
-
ConcurrentStream.setup(io)
|
275
|
-
io.add_callback do
|
276
|
-
@done = true
|
277
|
-
@streaming = false
|
278
|
-
end
|
279
|
-
else
|
280
|
-
@done = true
|
281
|
-
@streaming = false
|
282
|
-
end
|
283
|
-
|
284
|
-
@url = io.filename if io.filename
|
285
|
-
return io
|
286
|
-
end
|
287
|
-
|
288
|
-
WorkflowRESTClient.capture_exception do
|
289
|
-
@url = URI.encode(File.join(base_url, task.to_s))
|
290
|
-
task_params = inputs.merge(:_cache_type => cache_type, :jobname => base_name, :_format => [:string, :boolean, :tsv, :annotations].include?(result_type) ? :raw : :json)
|
291
|
-
|
292
|
-
sout, sin = Misc.pipe
|
293
|
-
streamer = lambda do |c|
|
294
|
-
sin.write c
|
295
|
-
end
|
296
|
-
|
297
|
-
post_thread = Thread.new(Thread.current) do |parent|
|
298
|
-
bl = lambda do |rok|
|
299
|
-
if Net::HTTPOK === rok
|
300
|
-
_url = rok["RBBT-STREAMING-JOB-URL"]
|
301
|
-
@url = File.join(@url, File.basename(_url)) if _url
|
302
|
-
rok.read_body do |c,_a, _b|
|
303
|
-
sin.write c
|
304
|
-
end
|
305
|
-
sin.close
|
306
|
-
else
|
307
|
-
parent.raise "Error in RestClient: " << rok.message
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
Log.debug{ "RestClient execute: #{ url } - #{Misc.fingerprint task_params}" }
|
312
|
-
RestClient::Request.execute(:method => :post, :url => url, :payload => task_params, :block_response => bl)
|
313
|
-
end
|
314
|
-
|
315
|
-
reader = Zlib::GzipReader.new(sout)
|
316
|
-
res_io = Misc.open_pipe do |sin|
|
317
|
-
while c = reader.read(Misc::BLOCK_SIZE)
|
318
|
-
sin.write c
|
319
|
-
end
|
320
|
-
sin.close
|
321
|
-
@done = true
|
322
|
-
end
|
323
|
-
|
324
|
-
ConcurrentStream.setup(res_io, :threads => [post_thread])
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
279
|
def exec_job
|
329
280
|
res = _run_job(:exec)
|
330
281
|
load_res res, result_type == :array ? :json : result_type
|
@@ -372,3 +323,5 @@ class WorkflowRESTClient
|
|
372
323
|
end
|
373
324
|
end
|
374
325
|
end
|
326
|
+
|
327
|
+
require 'rbbt/rest/client/run'
|