rbbt-util 5.27.5 → 5.27.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8792f1d19116c0384fd0063a5e81c8e9d9e30026e5dbaf41d5b26cf56210aa8
4
- data.tar.gz: d3c1cf57d737a5255c6f31eb3ebe907c21d8449a0fae89d0208bb2935b513903
3
+ metadata.gz: fe7c3dec4d2333e77ea396a2d6e572512bf7033999ff4715f1a1c6c9d3d1b9d5
4
+ data.tar.gz: 32a3d905c1a95f9c7e5cb359855f8781509cfeecdd8db7b77ee29eaea528d030
5
5
  SHA512:
6
- metadata.gz: d5f84745610ef5f21c23f193b17b2b16f7b4a6a17218e4e5a0d3e23fb68896d9039a99e6d72bf13952b2e39fb5b96b9809ca8683efdb788084c7ef688bac1c13
7
- data.tar.gz: 3f17849b28cfe2fd8618b72a74a9887172f90d93876ec59bbaae5d6fec4591537410958fcd5910805a6c995ebdef81e566d6056803090d8625efaccd0a3e2588
6
+ metadata.gz: d009024642898f775d423e1ddede6aea538e8ed5ff4675eedadd64768e67b0a46f6519038378a221db76b0e196cfc713ca8dc7553788cdb9a51014c14a97de4c
7
+ data.tar.gz: 5c0612feca84b00e6d402f7a68ca1cebd6f4b7a785b40899bdaed3385a3f68853824dcc98d9cfd2e641768ef5ca3d52e38e41bdbc1d7a3751ae288e8f8d7ed2d
@@ -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 or %w(memory stringio).include?(filename.to_s.downcase) or not File.exist?(filename)
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? filename.to_s.downcase
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
- @file = File.open(@filename, 'wb')
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 = StringIO.new(Open.read(@filename, :mode => 'r:ASCII-8BIT'), 'r')
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
- Open.mkdir(dir) unless Open.exists?(dir)
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 Open.exist?(File.dirname(path))
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
 
@@ -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? path
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? path + '.gz'
245
- path = path + '.bgz' if File.exist? path + '.bgz'
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 = @adaptor.parse_exception text
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
- RestClient::Request.execute(:method => :post, :url => task_url, :payload => task_params, :block_response => bl)
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
- digest = Misc.obj2digest([base_url, task, base_name, inputs])
29
- Rbbt.var.cache.REST[[task, clean_name, digest] * "."].find
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 = :async)
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
@@ -612,6 +612,10 @@ class Step
612
612
  provenance
613
613
  end
614
614
 
615
+ def resumable?
616
+ task && task.resumable
617
+ end
618
+
615
619
  def config(key, *tokens)
616
620
  options = tokens.pop if Hash === tokens.last
617
621
  options ||= {}
@@ -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
- Log.warn "Cleaning dep. on exec #{Log.color :blue, dependency.path} (missing: #{dependency.missing?}; error #{dependency.error?})"
148
- dependency.clean
149
- already_failed << dependency.path
150
- raise TryAgain
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
@@ -610,7 +610,7 @@ class Step
610
610
  end
611
611
 
612
612
  def _clean_finished
613
- if Open.exists? path and not status == :done
613
+ if Open.exists?(path) && status != :done
614
614
  Log.warn "Aborted job had finished. Removing result -- #{ path }"
615
615
  begin
616
616
  Open.rm path
@@ -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::INFO_SERIALIAZER.load(f)
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::INFO_SERIALIAZER.load(f)
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::INFO_SERIALIAZER.load(Open.read(file, :mode => 'rb'))
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::INFO_SERIALIAZER.load(Open.read(file, :mode => 'rb'))
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::INFO_SERIALIAZER.load(Open.read(options[:file], :mode => 'rb'))
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
- job = DepWorkflow.job(:task6, "TEST", :input_file => input_file)
156
- job.run(:stream)
157
- io = TSV.get_stream job
158
- while line = io.gets
159
- last_line = line.strip
160
- end
161
- io.join
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://turbo:Translation", "Translation"
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.5
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-05-12 00:00:00.000000000 Z
11
+ date: 2020-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake