rbbt-util 5.27.4 → 5.27.9

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rbbt/entity.rb +1 -1
  3. data/lib/rbbt/fix_width_table.rb +6 -5
  4. data/lib/rbbt/persist.rb +2 -2
  5. data/lib/rbbt/persist/tsv/tokyocabinet.rb +2 -2
  6. data/lib/rbbt/resource.rb +8 -5
  7. data/lib/rbbt/resource/path.rb +3 -3
  8. data/lib/rbbt/tsv/attach.rb +34 -30
  9. data/lib/rbbt/tsv/attach/util.rb +17 -0
  10. data/lib/rbbt/tsv/stream.rb +1 -0
  11. data/lib/rbbt/util/misc/exceptions.rb +8 -0
  12. data/lib/rbbt/util/misc/format.rb +1 -1
  13. data/lib/rbbt/util/misc/pipes.rb +37 -7
  14. data/lib/rbbt/util/tmpfile.rb +4 -4
  15. data/lib/rbbt/workflow.rb +2 -5
  16. data/lib/rbbt/workflow/accessor.rb +4 -2
  17. data/lib/rbbt/workflow/definition.rb +6 -0
  18. data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +12 -3
  19. data/lib/rbbt/workflow/remote_workflow/remote_step.rb +18 -4
  20. data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +7 -1
  21. data/lib/rbbt/workflow/step/accessor.rb +4 -0
  22. data/lib/rbbt/workflow/step/dependencies.rb +11 -7
  23. data/lib/rbbt/workflow/step/run.rb +1 -1
  24. data/lib/rbbt/workflow/task.rb +1 -1
  25. data/lib/rbbt/workflow/usage.rb +1 -1
  26. data/lib/rbbt/workflow/util/archive.rb +30 -4
  27. data/share/rbbt_commands/system/clean +2 -2
  28. data/share/rbbt_commands/system/status +3 -2
  29. data/share/rbbt_commands/tsv/uncollapse +29 -0
  30. data/share/rbbt_commands/workflow/info +1 -1
  31. data/share/rbbt_commands/workflow/monitor +3 -3
  32. data/share/rbbt_commands/workflow/task +2 -0
  33. data/test/rbbt/tsv/test_attach.rb +3 -2
  34. data/test/rbbt/tsv/test_stream.rb +4 -3
  35. data/test/rbbt/util/misc/test_format.rb +10 -0
  36. data/test/rbbt/util/misc/test_pipes.rb +1 -1
  37. data/test/rbbt/workflow/step/test_dependencies.rb +106 -17
  38. data/test/rbbt/workflow/test_remote_workflow.rb +13 -1
  39. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 002a8471d312055597b78dd78a842b8eca3349ef8330092db66c422b90a395d3
4
- data.tar.gz: 04e92168a2ff75cf3352b650b3976eb7f6bc376c0e261cd188c71e172182312d
3
+ metadata.gz: 88040e654ed6cb7818930897c0d66763e7f7834e7ea530ac0ef45e2b318ed078
4
+ data.tar.gz: b4813ae7c39189b7a17af4bd958a15823b506a293a03234c7f4cd7af773d37a4
5
5
  SHA512:
6
- metadata.gz: ca14d83e94da469aece65bc92ca4cbdff063ca3bc37d1d86c796eabb3dc8711466a440f8c3faf0686c608cb83a5c3f2b78b3a69479730a51e10ed18ba374dd28
7
- data.tar.gz: 8459a174d3767640b701c30ff3b425c3c01f10002a24c88a1e0734dee94f7e9f870d7ac144a39b54dade0d230784ecc22119e9d4e3f004edcd099d14c3280877
6
+ metadata.gz: f940c0f1c33c7a9afa7463ee04ff972cf2ec39ccf400bb6e5bb5abb94b54e9dba5c6a1dc2c1651f25f5e44284d5af7a405a436acd8cd1a6d0f143b14a2c8688b
7
+ data.tar.gz: 0d17a7e040af5a666d21a8a6db880ede4a50a7491e59476fe0288e6f9c444e174e34a27eec09aa15c6bccfb81e7348e1bb17b2f5ed5b9c115ea88b1321cf8265
@@ -261,7 +261,7 @@ module Entity
261
261
 
262
262
  define_method method_name do |*args|
263
263
  id = self.id
264
- persist_name = orig_method_name.to_s << ":" << (Array === id ? Misc.obj2digest(id) : id)
264
+ persist_name = orig_method_name.to_s + ":" << (Array === id ? Misc.obj2digest(id) : id)
265
265
 
266
266
  persist_options = options
267
267
  persist_options = persist_options.merge(:other => {:args => args}) if args and args.any?
@@ -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-8BIT'){|f| StringIO.new f.read}
31
32
  else
32
33
  @file = File.open(@filename, 'r:ASCII-8BIT')
33
34
  end
@@ -365,12 +365,12 @@ module Persist
365
365
  type ||= :marshal
366
366
 
367
367
  persist_options ||= {}
368
- if type == :memory and persist_options[:file] and persist_options[:persist]
368
+ if type == :memory && persist_options[:file] && persist_options[:persist]
369
369
  repo = persist_options[:repo] || Persist::MEMORY
370
370
  if persist_options[:persist] == :update || persist_options[:update]
371
371
  repo.delete persist_options[:file]
372
372
  end
373
- return repo[persist_options[:file]] ||= yield
373
+ return repo[persist_options[:file]] ||= yield
374
374
  end
375
375
 
376
376
  if FalseClass === persist_options[:persist]
@@ -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
 
@@ -170,10 +170,12 @@ module Resource
170
170
  if type and not File.exist?(final_path) or force
171
171
  Log.medium "Producing: #{ final_path }"
172
172
  lock_filename = Persist.persistence_path(final_path, {:dir => Resource.lock_dir})
173
+
173
174
  Misc.lock lock_filename do
174
175
  FileUtils.rm_rf final_path if force and File.exist? final_path
175
- if not File.exist?(final_path) or force
176
- (remote_server and get_from_server(path, final_path)) or
176
+
177
+ if ! File.exist?(final_path) || force
178
+
177
179
  begin
178
180
  case type
179
181
  when :string
@@ -291,7 +293,7 @@ url='#{url}'
291
293
  rescue
292
294
  FileUtils.rm_rf final_path if File.exist? final_path
293
295
  raise $!
294
- end
296
+ end unless (remote_server && get_from_server(path, final_path))
295
297
  end
296
298
  end
297
299
  end
@@ -304,11 +306,12 @@ url='#{url}'
304
306
  resource ||= Rbbt
305
307
  (Path::STANDARD_SEARCH + resource.search_order + resource.search_paths.keys).uniq.each do |name|
306
308
  pattern = resource.search_paths[name]
307
- next if patterns.nil?
309
+ next if pattern.nil?
310
+ pattern = pattern.sub('{PWD}', Dir.pwd)
308
311
  if String === pattern and pattern.include?('{')
309
312
  regexp = "^" + pattern.gsub(/{([^}]+)}/,'(?<\1>[^/]+)') + "(?:/(?<REST>.*))?/?$"
310
313
  if m = path.match(regexp)
311
- if m["PKGDIR"] == resource.pkgdir
314
+ if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == resource.pkgdir
312
315
  return self[m["TOPLEVEL"]][m["SUBPATH"]][m["REST"]]
313
316
  end
314
317
  end
@@ -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
 
@@ -32,7 +32,8 @@ module TSV
32
32
  done = false
33
33
  Open.write(output) do |os|
34
34
  options.delete :sep if options[:sep] == "\t"
35
- os.puts TSV.header_lines(key_field, fields, options)
35
+ header_lines = TSV.header_lines(key_field, fields, options)
36
+ os.puts header_lines unless header_lines.empty?
36
37
 
37
38
  while line
38
39
  key, *parts = line.sub("\n",'').split(sep, -1)
@@ -212,6 +213,35 @@ module TSV
212
213
  other_filename = other.respond_to?(:filename) ? other.filename : other.inspect
213
214
  Log.low("Attaching fields:#{Misc.fingerprint fields } from #{other_filename}.")
214
215
 
216
+ same_key = true
217
+ begin
218
+ case
219
+ when (Misc.match_fields(key_field, other.key_field) and same_key)
220
+ Log.debug "Attachment with same key: #{other.key_field}"
221
+ attach_same_key other, fields
222
+ when (not in_namespace and self.fields.select{|f| Misc.match_fields(f, other.key_field)}.any?)
223
+ Log.debug "Found other key field: #{other.key_field}"
224
+ attach_source_key other, other.key_field, :fields => fields, :one2one => one2one
225
+ when (in_namespace and self.fields_in_namespace.select{|f| Misc.match_fields(f, other.key_field)}.any?)
226
+ Log.debug "Found other key field in #{in_namespace}: #{other.key_field}"
227
+ attach_source_key other, other.key_field, :fields => fields, :one2one => one2one
228
+ else
229
+ index = TSV.find_traversal(self, other, options)
230
+ raise FieldNotFoundError, "Cannot traverse identifiers" if index.nil?
231
+ Log.debug "Attachment with index: #{other.key_field}"
232
+ attach_index other, index, fields
233
+ end
234
+ rescue Exception
235
+ if same_key
236
+ Log.warn "Could not translate identifiers with same_key"
237
+ same_key = false
238
+ retry
239
+ else
240
+ raise $!
241
+ end
242
+ end
243
+ Log.debug("Attachment of fields:#{Misc.fingerprint fields } from #{other.filename.inspect} finished.")
244
+
215
245
  if complete
216
246
  fill = TrueClass === complete ? nil : complete
217
247
  field_length = self.fields.length
@@ -219,6 +249,9 @@ module TSV
219
249
  other_common_pos = common_fields.collect{|f| other.fields.index f}
220
250
  this_common_pos = common_fields.collect{|f| self.fields.index f}
221
251
  missing = other.keys - self.keys
252
+
253
+ other = other.to_list if other.type == :single
254
+
222
255
  case type
223
256
  when :single
224
257
  missing.each do |k|
@@ -249,35 +282,6 @@ module TSV
249
282
  end
250
283
  end
251
284
 
252
- same_key = true
253
- begin
254
- case
255
- when (Misc.match_fields(key_field, other.key_field) and same_key)
256
- Log.debug "Attachment with same key: #{other.key_field}"
257
- attach_same_key other, fields
258
- when (not in_namespace and self.fields.select{|f| Misc.match_fields(f, other.key_field)}.any?)
259
- Log.debug "Found other key field: #{other.key_field}"
260
- attach_source_key other, other.key_field, :fields => fields, :one2one => one2one
261
- when (in_namespace and self.fields_in_namespace.select{|f| Misc.match_fields(f, other.key_field)}.any?)
262
- Log.debug "Found other key field in #{in_namespace}: #{other.key_field}"
263
- attach_source_key other, other.key_field, :fields => fields, :one2one => one2one
264
- else
265
- index = TSV.find_traversal(self, other, options)
266
- raise FieldNotFoundError, "Cannot traverse identifiers" if index.nil?
267
- Log.debug "Attachment with index: #{other.key_field}"
268
- attach_index other, index, fields
269
- end
270
- rescue Exception
271
- if same_key
272
- Log.warn "Could not translate identifiers with same_key"
273
- same_key = false
274
- retry
275
- else
276
- raise $!
277
- end
278
- end
279
- Log.debug("Attachment of fields:#{Misc.fingerprint fields } from #{other.filename.inspect} finished.")
280
-
281
285
  self
282
286
  end
283
287
 
@@ -4,9 +4,20 @@ module TSV
4
4
  fields = other.fields - [key_field].concat(self.fields) if fields.nil?
5
5
 
6
6
  fields = [fields].compact unless Array === fields
7
+
8
+ common_fields = self.fields & fields
9
+
10
+ fields = fields - common_fields
11
+
7
12
  num_fields = fields.length
8
13
 
9
14
  field_positions = fields.collect{|field| other.identify_field field}
15
+
16
+ if common_fields.any?
17
+ common_field_positions = common_fields.collect{|field| self.identify_field field}
18
+ common_field_positions_other = common_fields.collect{|field| other.identify_field field}
19
+ end
20
+
10
21
  other.with_unnamed do
11
22
  with_unnamed do
12
23
  through do |key, values|
@@ -28,6 +39,12 @@ module TSV
28
39
  new_values = field_positions.collect do |pos|
29
40
  pos == :key ? key : other_values[pos]
30
41
  end
42
+
43
+ if common_fields.any?
44
+ common_field_positions.zip(common_field_positions_other).each do |p1,p2|
45
+ current[p1] += other_values[p2]
46
+ end
47
+ end
31
48
  end
32
49
 
33
50
  new_values.collect!{|v| [v]} if type == :double and not (other.type == :double or other.type == :flat)
@@ -89,6 +89,7 @@ module TSV
89
89
  stream
90
90
  end
91
91
 
92
+ all_fields = fields
92
93
  key_field = key_fields.compact.first
93
94
  if same_fields
94
95
  fields = fields.first
@@ -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
 
@@ -163,7 +163,7 @@ module Misc
163
163
 
164
164
  def self.fixutf8(string)
165
165
  return nil if string.nil?
166
- return string if string.respond_to?(:encoding) && string.encoding == "UTF-8" && (string.respond_to?(:valid_encoding?) && string.valid_encoding?) ||
166
+ return string if string.respond_to?(:encoding) && string.encoding.to_s == "UTF-8" && (string.respond_to?(:valid_encoding?) && string.valid_encoding?) ||
167
167
  (string.respond_to?(:valid_encoding) && string.valid_encoding)
168
168
 
169
169
  if string.respond_to?(:encode)
@@ -18,6 +18,8 @@ module Misc
18
18
 
19
19
  BLOCK_SIZE=1024 * 8
20
20
 
21
+ SKIP_TAG="[SKIP TAG]"
22
+
21
23
  PIPE_MUTEX = Mutex.new
22
24
 
23
25
  OPEN_PIPE_IN = []
@@ -29,7 +31,7 @@ module Misc
29
31
 
30
32
  [sout, sin]
31
33
  end
32
- Log.debug{"Creating pipe #{[res.last.inspect,res.first.inspect] * " => "}"}
34
+ Log.debug{"Creating pipe #{[res.last.inspect, res.first.inspect] * " => "}"}
33
35
  res
34
36
  end
35
37
 
@@ -255,6 +257,11 @@ module Misc
255
257
  end
256
258
  tee1, *rest = Misc.tee_stream stream_dup, num + 1
257
259
  stream.reopen(tee1)
260
+
261
+ #ToDo: I can't explain why the @threads variable appears with the value of
262
+ # @filename
263
+ stream.instance_variable_set(:@threads, nil) if stream.instance_variables.include?(:@threads)
264
+
258
265
  tee1.annotate(stream)
259
266
  rest
260
267
  end
@@ -537,18 +544,29 @@ module Misc
537
544
  end
538
545
  end
539
546
 
547
+ def self.buffer_stream(stream)
548
+ sout, sin = Misc.pipe
549
+ Misc.consume_stream(stream, true, sin)
550
+ sout
551
+ end
552
+
540
553
  def self._paste_streams(streams, output, lines = nil, sep = "\t", header = nil, &block)
541
554
  output.puts header if header
542
555
  streams = streams.collect do |stream|
543
556
  if defined? Step and Step === stream
544
- stream.get_stream || stream.join.path.open
557
+ io = stream.get_stream
558
+ if io
559
+ buffer_stream(io)
560
+ else
561
+ stream.join.path.open
562
+ end
545
563
  else
546
564
  stream
547
565
  end
548
566
  end
549
567
 
550
568
  begin
551
- done_streams = []
569
+
552
570
  lines ||= streams.collect{|s| s.gets }
553
571
  keys = []
554
572
  parts = []
@@ -564,6 +582,7 @@ module Misc
564
582
  end
565
583
  sizes = parts.collect{|p| p.nil? ? 0 : p.length }
566
584
  last_min = nil
585
+
567
586
  while lines.compact.any?
568
587
  if block_given?
569
588
  min = keys.compact.sort(&block).first
@@ -571,14 +590,23 @@ module Misc
571
590
  min = keys.compact.sort.first
572
591
  end
573
592
  str = []
593
+ threads = []
574
594
  keys.each_with_index do |key,i|
575
595
  case key
576
596
  when min
577
- str << [parts[i] * sep]
597
+ if parts[i] == [SKIP_TAG]
598
+ str << [sep * (sizes[i]-1)] if sizes[i] > 0
599
+ else
600
+ str << [parts[i] * sep]
601
+ end
602
+
578
603
  line = lines[i] = streams[i].gets
579
- if line.nil?
604
+
605
+ if line.nil?
580
606
  keys[i] = nil
581
607
  parts[i] = nil
608
+ streams[i].close unless streams[i].closed?
609
+ streams[i].join if streams[i].respond_to?(:join)
582
610
  else
583
611
  k, *p = line.chomp.split(sep, -1)
584
612
  keys[i] = k
@@ -589,10 +617,12 @@ module Misc
589
617
  end
590
618
  end
591
619
 
592
- output.puts [min, str*sep] * sep
620
+ output.puts [min, str.flatten*sep] * sep
593
621
  end
622
+
594
623
  streams.each do |stream|
595
- stream.join if stream.respond_to? :join
624
+ stream.close unless stream.closed?
625
+ stream.join if stream.respond_to?(:join)
596
626
  end
597
627
  rescue
598
628
  Log.exception $!
@@ -17,14 +17,14 @@ module TmpFile
17
17
 
18
18
  # Creates a random file name, with the given suffix and a random number
19
19
  # up to +max+
20
- def self.random_name(s = "tmp-", max = 10000000)
20
+ def self.random_name(s = "tmp-", max = 1_000_000_000)
21
21
  n = rand(max)
22
22
  s + n.to_s
23
23
  end
24
24
 
25
25
  # Creates a random filename in the temporary directory
26
- def self.tmp_file(s = "tmp-", max=10000000, dir = TMPDIR)
27
- File.expand_path(File.join(dir, random_name(s,max)))
26
+ def self.tmp_file(s = "tmp-", max=1_000_000_000, dir = TMPDIR)
27
+ File.expand_path(File.join(dir, random_name(s, max)))
28
28
  end
29
29
 
30
30
  def self.with_file(content = nil, erase = true, options = {})
@@ -33,7 +33,7 @@ module TmpFile
33
33
 
34
34
  prefix = options[:prefix] || "tmp-"
35
35
  tmpdir = options[:tmpdir] || TMPDIR
36
- max = options[:max] || 10000000
36
+ max = options[:max] || 1_000_000_000
37
37
  tmpfile = tmp_file prefix, max, tmpdir
38
38
  if options[:extension]
39
39
  tmpfile += ".#{options[:extension]}"
@@ -10,9 +10,6 @@ require 'rbbt/workflow/util/provenance'
10
10
 
11
11
  module Workflow
12
12
 
13
- STEP_CACHE = {}
14
- LOAD_STEP_CACHE = {}
15
-
16
13
  class TaskNotFoundException < Exception
17
14
  def initialize(workflow, task = nil)
18
15
  if task
@@ -264,11 +261,11 @@ module Workflow
264
261
  end
265
262
 
266
263
  def step_cache
267
- @step_cache ||= Workflow::STEP_CACHE
264
+ Thread.current[:step_cache] ||= {}
268
265
  end
269
266
 
270
267
  def self.load_step_cache
271
- @load_step_cache ||= Workflow::LOAD_STEP_CACHE
268
+ Thread.current[:load_step_cache] ||= {}
272
269
  end
273
270
 
274
271
 
@@ -35,6 +35,7 @@ module Workflow
35
35
  input_use = rec_input_use(name)
36
36
  input_defaults = rec_input_defaults(name)
37
37
  input_options = rec_input_options(name)
38
+ extension = task.extension
38
39
  export = case
39
40
  when (synchronous_exports.include?(name.to_sym) or synchronous_exports.include?(name.to_s))
40
41
  :synchronous
@@ -60,7 +61,8 @@ module Workflow
60
61
  :input_use => input_use,
61
62
  :result_type => result_type,
62
63
  :result_description => result_description,
63
- :dependencies => dependencies
64
+ :dependencies => dependencies,
65
+ :extension => extension
64
66
  }
65
67
  end
66
68
  end
@@ -416,7 +418,7 @@ module Workflow
416
418
  when :hash
417
419
  clean_inputs = Annotated.purge(inputs)
418
420
  clean_inputs = clean_inputs.collect{|i| Symbol === i ? i.to_s : i }
419
- deps_str = dependencies.collect{|d| Step === d ? d.short_path : d }
421
+ deps_str = dependencies.collect{|d| (Step === d || (defined?(RemoteStep) && RemoteStep === Step)) ? "Step: " << d.short_path : d }
420
422
  key_obj = {:inputs => clean_inputs, :dependencies => deps_str }
421
423
  key_str = Misc.obj2str(key_obj)
422
424
  hash_str = Misc.digest(key_str)
@@ -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,17 @@ 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
+ case rok
141
+ when Net::HTTPOK
141
142
  _url = rok["RBBT-STREAMING-JOB-URL"]
142
143
  @url = File.join(task_url, File.basename(_url)) if _url
143
144
  rok.read_body do |c,_a, _b|
144
145
  sin.write c
145
146
  end
146
147
  sin.close
148
+ when Net::HTTPRedirection, Net::HTTPAccepted
149
+ Thread.current.report_on_exception = false
150
+ raise TryThis.new(rok)
147
151
  else
148
152
  err = StringIO.new
149
153
  rok.read_body do |c,_a, _b|
@@ -156,7 +160,7 @@ class RemoteWorkflow
156
160
  err.rewind
157
161
  err.read
158
162
  end
159
- ne = @adaptor.parse_exception text
163
+ ne = RemoteWorkflow.parse_exception text
160
164
  case ne
161
165
  when String
162
166
  parent.raise e.class, ne
@@ -173,7 +177,12 @@ class RemoteWorkflow
173
177
  end
174
178
 
175
179
  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)
180
+ begin
181
+ RestClient::Request.execute(:method => :post, :url => task_url, :payload => task_params, :block_response => bl)
182
+ rescue TryThis
183
+ url = $!.payload["location"]
184
+ RestClient::Request.execute(:method => :get, :url => url, :block_response => bl)
185
+ end
177
186
  end
178
187
 
179
188
  # 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.to_s, base_name, inputs])
30
+ Rbbt.var.cache.REST[task.to_s][[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|
@@ -139,7 +143,11 @@ class RemoteStep < Step
139
143
  @info = Persist.memory("RemoteSteps Info", :url => @url, :persist => true, :update => update) do
140
144
  @last_info_time = Time.now
141
145
  init_job unless @url
142
- info = @adaptor.get_json(File.join(@url, 'info'))
146
+ info = begin
147
+ @adaptor.get_json(File.join(@url, 'info'))
148
+ rescue
149
+ {:status => :noinfo}
150
+ end
143
151
  info = RemoteWorkflow.fix_hash(info)
144
152
  info[:status] = info[:status].to_sym if String === info[:status]
145
153
  info
@@ -239,7 +247,9 @@ class RemoteStep < Step
239
247
  def join
240
248
  return true if cache_files.any?
241
249
  init_job unless @url
250
+ produce unless @started
242
251
  Log.debug{ "Joining RemoteStep: #{path}" }
252
+
243
253
  if IO === @result
244
254
  res = @result
245
255
  @result = nil
@@ -305,6 +315,10 @@ class RemoteStep < Step
305
315
  end
306
316
  end
307
317
 
318
+ def short_path
319
+ init_job unless @url
320
+ [@task, @name] * "/"
321
+ end
308
322
 
309
323
  def input_checks
310
324
  []
@@ -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
@@ -362,7 +366,7 @@ class Step
362
366
  (step.dependencies + step.input_dependencies).each do |step_dep|
363
367
  next if step_dep.done? or step_dep.running? or (ComputeDependency === step_dep and (step_dep.compute == :nodup or step_dep.compute == :ignore))
364
368
  dep_step[step_dep.path] ||= []
365
- dep_step[step_dep.path] << step_dep
369
+ dep_step[step_dep.path] << step
366
370
  end
367
371
  end
368
372
 
@@ -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
@@ -88,7 +88,7 @@ module Workflow
88
88
  key = [workflow, task]
89
89
 
90
90
  dep_tree[key] = workflow.dep_tree(task)
91
- end if self.task_dependencies[name.to_sym]
91
+ end if name && self.task_dependencies[name.to_sym]
92
92
  dep_tree
93
93
  end
94
94
  end
@@ -125,6 +125,7 @@ class Step
125
125
  def self.migrate(path, search_path, options = {})
126
126
  resource=Rbbt
127
127
 
128
+ orig_path = path
128
129
  other_rsync_args = options[:rsync]
129
130
 
130
131
  recursive = options[:recursive]
@@ -154,6 +155,7 @@ puts files * "\n"
154
155
  else
155
156
  if File.exists?(path)
156
157
  path = resource.identify(path)
158
+ raise "Resource #{resource} could not identify #{orig_path}" if path.nil?
157
159
  else
158
160
  path = Path.setup(path)
159
161
  end
@@ -178,7 +180,7 @@ puts resource[path].find(search_path)
178
180
  subpath_files = {}
179
181
  paths.sort.each do |path|
180
182
  parts = path.split("/")
181
- subpath = parts[0..-4] * "/"
183
+ subpath = parts[0..-4] * "/" + "/"
182
184
 
183
185
  if subpath_files.keys.any? && subpath.start_with?(subpath_files.keys.last)
184
186
  subpath = subpath_files.keys.last
@@ -190,6 +192,7 @@ puts resource[path].find(search_path)
190
192
  subpath_files[subpath] << source
191
193
  end
192
194
 
195
+ synced_files = []
193
196
  subpath_files.each do |subpath, files|
194
197
  if options[:target]
195
198
  CMD.cmd("ssh #{options[:target]} mkdir -p '#{File.dirname(target)}'")
@@ -204,11 +207,15 @@ puts resource[path].find(search_path)
204
207
  end
205
208
  target = [options[:target], target] * ":" if options[:target]
206
209
 
210
+ next if File.exists?(source) && File.exists?(target) && File.expand_path(source) == File.expand_path(target)
211
+
207
212
  files_and_dirs = Set.new( files )
208
213
  files.each do |file|
214
+ synced_files << File.join(subpath, file)
215
+
209
216
  parts = file.split("/")[0..-2].reject{|p| p.empty?}
210
217
  while parts.any?
211
- files_and_dirs << parts * "/"
218
+ files_and_dirs << parts * "/"
212
219
  parts.pop
213
220
  end
214
221
  end
@@ -218,8 +225,7 @@ puts resource[path].find(search_path)
218
225
 
219
226
  cmd = "rsync #{MAIN_RSYNC_ARGS} --progress #{test_str} --files-from='#{tmp_include_file}' #{source}/ #{target}/ #{other_rsync_args}"
220
227
 
221
- cmd << " && rm -Rf #{source}" if options[:delete]
222
-
228
+ #cmd << " && rm -Rf #{source}" if options[:delete]
223
229
  if options[:print]
224
230
  ppp Open.read(tmp_include_file)
225
231
  puts cmd
@@ -228,6 +234,26 @@ puts resource[path].find(search_path)
228
234
  end
229
235
  end
230
236
  end
237
+
238
+ if options[:delete] && synced_files.any?
239
+ puts Log.color :magenta, "About to erase these files:"
240
+ synced_files.each do |p|
241
+ puts Log.color :red, p
242
+ end
243
+
244
+ if options[:non_interactive]
245
+ response = 'yes'
246
+ else
247
+ puts Log.color :magenta, "Type 'yes' if you are sure:"
248
+ response = STDIN.gets.chomp
249
+ end
250
+
251
+ if response == 'yes'
252
+ synced_files.each do |p|
253
+ Open.rm p
254
+ end
255
+ end
256
+ end
231
257
  end
232
258
 
233
259
  def self.purge(path, recursive = false)
@@ -97,7 +97,7 @@ TSV.traverse jobs do |file,i|
97
97
  else
98
98
  info = begin
99
99
  Open.open(i[:info_file]) do |f|
100
- Step::INFO_SERIALIAZER.load(f)
100
+ Step::INFO_SERIALIZER.load(f)
101
101
  end
102
102
  rescue
103
103
  {:status => :noinfo}
@@ -134,7 +134,7 @@ TSV.traverse jobs do |file,i|
134
134
  end
135
135
  end
136
136
 
137
- if (force and status !~ /done/) or
137
+ if (force && status !~ /done/) or
138
138
  status =~ /\b(old|dirty|nopid|error|missing|aborted|dead|sync)$/ or
139
139
  (status == "noinfo" and not done) or
140
140
  status == ""
@@ -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)
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbbt-util'
4
+ require 'rbbt/util/simpleopt'
5
+
6
+ options = SOPT.setup <<EOF
7
+ Read a TSV file and dump it
8
+
9
+ $ rbbt tsv read [options] <filename.tsv|->
10
+
11
+ Use - to read from STDIN
12
+
13
+ -k--key_field* Key field
14
+ -f--fields* Fields
15
+ -t--type* Type
16
+ -m--merge* Merge from multiple rows
17
+ -h--help Print this help
18
+
19
+ EOF
20
+ rbbt_usage and exit 0 if options[:help]
21
+
22
+ file = ARGV.shift
23
+
24
+ file = STDIN if file == '-'
25
+
26
+ tsv = TSV.open file, :merge => true, :type => :double
27
+
28
+
29
+ puts tsv.to_unmerged_expanded_s
@@ -153,7 +153,7 @@ if recursive
153
153
  dep = deps.shift
154
154
  inputs = {} if inputs.nil?
155
155
  inputs = inputs.merge(dep.info[:inputs] || {})
156
- deps = deps.concat dep.dependencies
156
+ deps = deps.concat dep.dependencies if dep.dependencies
157
157
  end
158
158
 
159
159
  inputs = inputs.merge step.archived_inputs
@@ -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
@@ -337,6 +337,8 @@ if clean_task
337
337
  dep.clean
338
338
  dep.set_info :status, :cleaned
339
339
  end
340
+
341
+ job.clean if job.task_name.to_s == clean_task.to_s
340
342
  end
341
343
  end
342
344
 
@@ -213,8 +213,9 @@ row2 E
213
213
 
214
214
  tsv1 = tsv2 = nil
215
215
 
216
- tsv1 = Rbbt.tmp.test.test1.data.tsv :double, :sep => /\s+/
217
- tsv2 = Rbbt.tmp.test.test2.data.tsv :double, :sep => /\s+/
216
+ tsv1 = Rbbt.tmp.test.test1.data.produce(true).tsv :double, :sep => /\s+/
217
+ tsv2 = Rbbt.tmp.test.test2.data.produce(true).tsv :double, :sep => /\s+/
218
+ Log.tsv tsv2
218
219
 
219
220
  tsv2.identifiers = Rbbt.tmp.test.test2.identifiers.produce.find #.to_s
220
221
 
@@ -4,6 +4,7 @@ require 'rbbt/tsv/stream'
4
4
  require 'rbbt'
5
5
 
6
6
  class TestStream < Test::Unit::TestCase
7
+
7
8
  def test_collapse_stream
8
9
  text=<<-EOF
9
10
  #: :sep=" "
@@ -65,7 +66,7 @@ row3 AAA BBB CCC
65
66
 
66
67
  text2=<<-EOF
67
68
  #: :sep=" "
68
- #Row Labela Labelb
69
+ #Row Labela Labelb
69
70
  row1 a b
70
71
  row3 aaa bbb
71
72
  row2 aa bb
@@ -100,7 +101,7 @@ row1 A B C
100
101
 
101
102
  text2=<<-EOF
102
103
  #: :sep=" "
103
- #Row Labela Labelb
104
+ #Row Labela Labelb
104
105
  row2 aa bb
105
106
  EOF
106
107
 
@@ -132,7 +133,7 @@ row1 A B C
132
133
 
133
134
  text2=<<-EOF
134
135
  #: :sep=" "
135
- #Row Labela Labelb
136
+ #Row Labela Labelb
136
137
  row2 aa bb
137
138
  EOF
138
139
 
@@ -0,0 +1,10 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
2
+ require 'rbbt/util/misc/format'
3
+
4
+ class TestClass < Test::Unit::TestCase
5
+ def test_fixutf8
6
+ a = "Camión"
7
+ assert_equal a, Misc.fixutf8(a)
8
+ end
9
+ end
10
+
@@ -285,7 +285,7 @@ line4
285
285
  begin
286
286
  Misc.consume_stream(sio, false, STDOUT)
287
287
  rescue
288
- Log.exception $!
288
+ raise $!
289
289
  end
290
290
  end
291
291
  end
@@ -4,6 +4,27 @@ require 'rbbt/workflow'
4
4
  module DepWorkflow
5
5
  extend Workflow
6
6
 
7
+ input :input_file, :file, "Input file", nil, :stream => true
8
+ task :s1 => :array do |input_file|
9
+ TSV.traverse input_file, :type => :array, :into => :stream, :bar => "Task1" do |line|
10
+ line + "\t" << "Task1"
11
+ end
12
+ end
13
+
14
+ dep :s1
15
+ task :s2 => :array do |input_file|
16
+ TSV.traverse step(:s1), :type => :array, :into => :stream, :bar => "Task2" do |line|
17
+ next [line.split("\t").first, Misc::SKIP_TAG] * "\t" if rand < 0.9
18
+ line + "\t" << "Task2"
19
+ end
20
+ end
21
+
22
+ dep :s1
23
+ dep :s2
24
+ task :s3 => :array do |input_file|
25
+ Misc.paste_streams(dependencies.reverse)
26
+ end
27
+
7
28
  input :input_file, :file, "Input file", nil, :stream => true
8
29
  task :task1 => :array do |input_file|
9
30
  TSV.traverse input_file, :type => :array, :into => :stream, :bar => "Task1" do |line|
@@ -28,9 +49,7 @@ module DepWorkflow
28
49
  dep :task2
29
50
  dep :task3
30
51
  task :task4 => :array do
31
- s1 = TSV.get_stream step(:task2)
32
- s2 = TSV.get_stream step(:task3)
33
- Misc.paste_streams([s1, s2])
52
+ Misc.paste_streams(dependencies)
34
53
  end
35
54
 
36
55
  dep :task4
@@ -43,9 +62,7 @@ module DepWorkflow
43
62
  dep :task2
44
63
  dep :task5
45
64
  task :task6 => :array do
46
- s1 = TSV.get_stream step(:task2)
47
- s2 = TSV.get_stream step(:task5)
48
- Misc.paste_streams([s1, s2])
65
+ Misc.paste_streams(dependencies)
49
66
  end
50
67
 
51
68
  input :stream_file, :file, "Streamed file", nil, :stream => true
@@ -81,6 +98,26 @@ module ComputeWorkflow
81
98
 
82
99
  end
83
100
 
101
+ module ResumeWorkflow
102
+ extend Workflow
103
+
104
+ resumable
105
+ task :resume => :string do
106
+ if file('foo').exists?
107
+ 'done'
108
+ else
109
+ Open.mkdir files_dir
110
+ Open.touch(file('foo'))
111
+ raise
112
+ end
113
+ end
114
+
115
+ dep :resume
116
+ task :reverse => :string do
117
+ step(:resume).load.reverse
118
+ end
119
+ end
120
+
84
121
  class TestWorkflowDependency < Test::Unit::TestCase
85
122
  def test_task1
86
123
  size = 10000
@@ -114,8 +151,25 @@ class TestWorkflowDependency < Test::Unit::TestCase
114
151
  end
115
152
  end
116
153
 
154
+ def test_task3
155
+ size = 100000
156
+ content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
157
+ TmpFile.with_file(content) do |input_file|
158
+ job = DepWorkflow.job(:task3, "TEST", :input_file => input_file)
159
+ io = TSV.get_stream job.run(:stream)
160
+ last_line = nil
161
+ while line = io.gets
162
+ last_line = line.strip
163
+ end
164
+ io.join
165
+
166
+ assert_equal "Line #{size}\tTask1\tTask3", last_line
167
+ end
168
+ end
169
+
117
170
  def test_task4
118
- size = 1000
171
+ size = 100000
172
+ Log.severity = 0
119
173
  content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
120
174
  last_line = nil
121
175
  TmpFile.with_file(content) do |input_file|
@@ -131,7 +185,7 @@ class TestWorkflowDependency < Test::Unit::TestCase
131
185
  end
132
186
 
133
187
  def test_task5
134
- size = 1000
188
+ size = 10000
135
189
  content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
136
190
  last_line = nil
137
191
  TmpFile.with_file(content) do |input_file|
@@ -145,20 +199,44 @@ class TestWorkflowDependency < Test::Unit::TestCase
145
199
  assert_equal "Line #{size}\tTask1\tTask2\tTask1\tTask3\tTask5", last_line
146
200
  end
147
201
 
148
- def test_task6
202
+ def test_s3
149
203
  size = 100000
150
- content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
204
+ content = (1..size).to_a.collect{|num| "Line #{num}" } * "\n"
151
205
  last_line = nil
152
206
  Log.severity = 0
153
207
  TmpFile.with_file(content) do |input_file|
154
208
  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
209
+ job = DepWorkflow.job(:s3, "TEST", :input_file => input_file)
210
+ job.recursive_clean
211
+ job.run(:stream)
212
+ io = TSV.get_stream job
213
+ while line = io.gets
214
+ last_line = line.strip
215
+ end
216
+ io.join if io.respond_to? :join
217
+ rescue Exception
218
+ job.abort
219
+ raise $!
160
220
  end
161
- io.join
221
+ end
222
+ assert last_line.include? "Line #{size}"
223
+ end
224
+
225
+ def test_task6
226
+ size = 100000
227
+ content = (1..size).to_a.collect{|num| "Line #{num}" } * "\n"
228
+ last_line = nil
229
+ Log.severity = 0
230
+ TmpFile.with_file(content) do |input_file|
231
+ begin
232
+ job = DepWorkflow.job(:task6, "TEST", :input_file => input_file)
233
+ job.recursive_clean
234
+ job.run(:stream)
235
+ io = TSV.get_stream job
236
+ while line = io.gets
237
+ last_line = line.strip
238
+ end
239
+ io.join
162
240
  rescue Exception
163
241
  job.abort
164
242
  raise $!
@@ -168,7 +246,7 @@ class TestWorkflowDependency < Test::Unit::TestCase
168
246
  end
169
247
 
170
248
  def test_task8
171
- size = 100000
249
+ size = 10000
172
250
  content = (0..size).to_a.collect{|num| "Line #{num}" } * "\n"
173
251
  last_line = nil
174
252
  Log.severity = 0
@@ -204,5 +282,16 @@ class TestWorkflowDependency < Test::Unit::TestCase
204
282
  assert_equal "Line #{size}\tTask1\tTask2", last_line
205
283
  end
206
284
  end
285
+
286
+ def test_resume
287
+ Log.severity = 0
288
+ job = ResumeWorkflow.job(:reverse)
289
+ job.recursive_clean
290
+ assert_raise do
291
+ job.run
292
+ end
293
+ assert job.dependencies.first.file('foo').exists?
294
+ assert_equal 'done'.reverse, job.run
295
+ end
207
296
  end
208
297
 
@@ -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.4
4
+ version: 5.27.9
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-05 00:00:00.000000000 Z
11
+ date: 2020-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -403,6 +403,7 @@ files:
403
403
  - share/rbbt_commands/tsv/sort
404
404
  - share/rbbt_commands/tsv/subset
405
405
  - share/rbbt_commands/tsv/transpose
406
+ - share/rbbt_commands/tsv/uncollapse
406
407
  - share/rbbt_commands/tsv/unzip
407
408
  - share/rbbt_commands/tsv/values
408
409
  - share/rbbt_commands/tsv/write_excel
@@ -487,6 +488,7 @@ files:
487
488
  - test/rbbt/util/concurrency/test_threads.rb
488
489
  - test/rbbt/util/log/test_progress.rb
489
490
  - test/rbbt/util/misc/test_bgzf.rb
491
+ - test/rbbt/util/misc/test_format.rb
490
492
  - test/rbbt/util/misc/test_lock.rb
491
493
  - test/rbbt/util/misc/test_multipart_payload.rb
492
494
  - test/rbbt/util/misc/test_omics.rb
@@ -552,6 +554,7 @@ test_files:
552
554
  - test/rbbt/util/test_colorize.rb
553
555
  - test/rbbt/util/misc/test_omics.rb
554
556
  - test/rbbt/util/misc/test_pipes.rb
557
+ - test/rbbt/util/misc/test_format.rb
555
558
  - test/rbbt/util/misc/test_lock.rb
556
559
  - test/rbbt/util/misc/test_multipart_payload.rb
557
560
  - test/rbbt/util/misc/test_bgzf.rb