miga-base 1.3.20.10 → 1.3.20.11

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: 89f86ec82f63d08729e4f970919dba5762a2888c797cdf6a8a7f32805929508c
4
- data.tar.gz: cb3e930ba1a4acb776bd7bcc7481470363109c2c01a67e1780f1d71dc29659c0
3
+ metadata.gz: 91302d7d75ccc35b6ff9606f8b6d777f1ed9d003884b1239ccf88d1a60e9cd23
4
+ data.tar.gz: d71e38b02f3e54695a4e2c40b07b910ebaf8719511f20fb5c19198aa9b4dbae2
5
5
  SHA512:
6
- metadata.gz: aa6434515aaca67b727e2a725cd2013e3096eb638cfc590e452c4e33c0e72f4c788b14cc0e8254cb91f14082330c038fa826ecab2cca01ccc2d4f96272ce0bac
7
- data.tar.gz: f5aec44b327725934d7585e157a68a653c9567743c46120e90d5280638935194684829acaa0003ff14ed239ee07ead6a604e25d423743986f627cb379767614c
6
+ metadata.gz: e0df7e189c74f4c791493d04f14000671c40a2fe5d9a50c92985a82eb0b7fe9670205a8d5b01ab7fb158df9836fb5d41040c1cf3ac81321dd66dde84d01adbe3
7
+ data.tar.gz: 0f30aac316c440e623405eab59855a3ace6d5bc04e452bfe67d67c1cb486670a48a629e0fd9f631cdd66446907147043d80d03e273423a620074d5a320bd3975
@@ -37,11 +37,12 @@ module MiGA::Cli::Action::Doctor::Base
37
37
  return if fix.empty?
38
38
 
39
39
  cli.say("- Fixing #{fix.size} datasets")
40
- MiGA::Parallel.distribute(fix, cli[:threads]) do |d_n, idx, thr|
40
+ o = MiGA::Parallel.distribute(fix, cli[:threads]) do |d_n, idx, thr|
41
41
  cli.advance(' > Fixing', idx + 1, fix.size, false) if thr == 0
42
42
  p.dataset(d_n).cleanup_distances!
43
43
  end
44
44
  cli.say
45
+ MiGA::Parallel.assess_success(o)
45
46
  end
46
47
 
47
48
  ##
@@ -103,7 +103,7 @@ module MiGA::Cli::Action::Doctor::Distances
103
103
  # Read data (threaded)
104
104
  FileUtils.mkdir_p(tmp)
105
105
  chunks_e = 0 .. chunks - 1
106
- MiGA::Parallel.distribute(chunks_e, cli[:threads]) do |chunk, k, thr|
106
+ o = MiGA::Parallel.distribute(chunks_e, cli[:threads]) do |chunk, k, thr|
107
107
  cli.advance('Reading:', k, chunks, false) if thr == 0
108
108
  dist = {}
109
109
  [:aai, :ani].each do |metric|
@@ -121,6 +121,7 @@ module MiGA::Cli::Action::Doctor::Distances
121
121
  end
122
122
  cli.advance('Reading:', chunks, chunks, false)
123
123
  cli.say
124
+ MiGA::Parallel.assess_success(o)
124
125
 
125
126
  # Save information to indicate that the run is complete and return
126
127
  File.open(tmp_chunks, 'w') { |fh| fh.puts(chunks, n) }
@@ -135,12 +136,12 @@ module MiGA::Cli::Action::Doctor::Distances
135
136
  tmp_done = File.join(tmp, 'chunks.txt')
136
137
  chunks = File.readlines(tmp_done)[0].chomp.to_i
137
138
 
138
- lower_triangle = []
139
+ lower_tr = []
139
140
  chunks.times.each do |i|
140
- (0 .. i).to_a.each { |j| lower_triangle << [i, j] }
141
+ (0 .. i).to_a.each { |j| lower_tr << [i, j] }
141
142
  end
142
- MiGA::Parallel.distribute(lower_triangle, cli[:threads]) do |cell, k, thr|
143
- cli.advance('Writing:', k, lower_triangle.size, false) if thr == 0
143
+ o = MiGA::Parallel.distribute(lower_tr, cli[:threads]) do |cell, k, thr|
144
+ cli.advance('Writing:', k, lower_tr.size, false) if thr == 0
144
145
  done_f = File.join(tmp, "#{cell[0]}-#{cell[1]}.txt")
145
146
  next if File.exist?(done_f)
146
147
 
@@ -148,9 +149,11 @@ module MiGA::Cli::Action::Doctor::Distances
148
149
  File.open("#{done_f}.tmp", 'w') { |fh| fixed_ds.each { |ds| fh.puts ds } }
149
150
  File.rename("#{done_f}.tmp", done_f)
150
151
  end
151
- cli.advance('Writing:', lower_triangle.size, lower_triangle.size, false)
152
+ cli.advance('Writing:', lower_tr.size, lower_tr.size, false)
152
153
  cli.say
153
- lower_triangle.map do |cell|
154
+ MiGA::Parallel.assess_success(o)
155
+
156
+ lower_tr.map do |cell|
154
157
  Set.new.tap do |y|
155
158
  file = File.join(tmp, "#{cell[0]}-#{cell[1]}.txt")
156
159
  raise MiGA::Error.new(
data/lib/miga/common.rb CHANGED
@@ -106,13 +106,13 @@ class MiGA::MiGA
106
106
  ''
107
107
  else
108
108
  left_time = @_advance_time[:avg] * (total - n) / 60 # <- in minutes
109
- left_time < 0.01 ? ' ' :
110
- left_time < 1 ? ('%.0fs left' % (left_time * 60)) :
109
+ left_time < 0.01 ? '' :
110
+ left_time < 1 ? ('%.0fs left' % (left_time * 60)) :
111
111
  left_time > 1440 ? ('%.1fd left' % (left_time / 1440)) :
112
- left_time > 60 ? ('%.1fh left' % (left_time / 60)) :
112
+ left_time > 60 ? ('%.1fh left' % (left_time / 60)) :
113
113
  ('%.1fm left' % left_time)
114
114
  end
115
- $stderr.print("[%s] %s %s %s \r" % [Time.now, step, adv, left])
115
+ $stderr.print("[%s] %s %s %-12s \r" % [Time.now, step, adv, left])
116
116
  end
117
117
 
118
118
  ##
data/lib/miga/parallel.rb CHANGED
@@ -8,10 +8,9 @@ class MiGA::Parallel < MiGA::MiGA
8
8
  # Executes the passed block with the thread number as argument (0-numbered)
9
9
  # in +threads+ processes
10
10
  def process(threads)
11
- threads.times do |i|
12
- Process.fork { yield(i) }
13
- end
14
- Process.waitall
11
+ threads.times
12
+ .map { |i| Process.fork { yield(i) } }
13
+ .map { |pid| Process.waitpid2(pid) }
15
14
  end
16
15
 
17
16
  ##
@@ -21,7 +20,6 @@ class MiGA::Parallel < MiGA::MiGA
21
20
  # 3. Index of the acting thread
22
21
  def distribute(enum, threads, &blk)
23
22
  process(threads) { |thr| thread_enum(enum, threads, thr, &blk) }
24
- Process.waitall # <- Just to double-check, but `process` should suffice
25
23
  end
26
24
 
27
25
  ##
@@ -33,5 +31,23 @@ class MiGA::Parallel < MiGA::MiGA
33
31
  yield(obj, idx, thr) if idx % threads == thr
34
32
  end
35
33
  end
34
+
35
+ ##
36
+ # Assesses the success of all thread exit codes and raises an error if
37
+ # any of the children status in +status+ failed. It can be used as:
38
+ #
39
+ # status = MiGA::Parallel.process(3) { |i| 1/i }
40
+ # MiGA::Parallel.assess_success(status)
41
+ #
42
+ # Or in conjunction with +MiGA::Parallel.distribute+
43
+ def assess_success(status)
44
+ failed = status.map { |i| i[1].success? ? 0 : 1 }.inject(:+)
45
+ return if failed.zero?
46
+
47
+ raise MiGA::Error.new(
48
+ "Child threads failed: #{failed}/#{status.size}. " \
49
+ "Maximum exit status: #{status.map { |i| i[1].exitstatus || 0 }.max}"
50
+ )
51
+ end
36
52
  end
37
53
  end
data/lib/miga/version.rb CHANGED
@@ -12,7 +12,7 @@ module MiGA
12
12
  # - String indicating release status:
13
13
  # - rc* release candidate, not released as gem
14
14
  # - [0-9]+ stable release, released as gem
15
- VERSION = [1.3, 20, 10].freeze
15
+ VERSION = [1.3, 20, 11].freeze
16
16
 
17
17
  ##
18
18
  # Nickname for the current major.minor version.
@@ -20,7 +20,7 @@ module MiGA
20
20
 
21
21
  ##
22
22
  # Date of the current gem relese.
23
- VERSION_DATE = Date.new(2024, 9, 12)
23
+ VERSION_DATE = Date.new(2024, 9, 13)
24
24
 
25
25
  ##
26
26
  # References of MiGA
@@ -19,6 +19,18 @@ class ParallelTest < Test::Unit::TestCase
19
19
  assert_equal([0, 0, 1, 1], t.sort)
20
20
  end
21
21
 
22
+ def test_assess_success
23
+ declare_forks
24
+
25
+ o = MiGA::Parallel.process(1) { |i| i / 2 }
26
+ assert(o.all? { |i| i[1].success? })
27
+ assert_nil(MiGA::Parallel.assess_success(o))
28
+
29
+ o = MiGA::Parallel.process(1) { |i| $stderr = StringIO.new ; 1 / i }
30
+ assert_equal(1, o.map { |i| i[1].success? ? 0 : 1 }.inject(:+))
31
+ assert_raise { MiGA::Parallel.assess_success(o) }
32
+ end
33
+
22
34
  def test_thread_enum
23
35
  MiGA::Parallel.thread_enum(%w[a b c d], 3, 1) do |o, _k, _t|
24
36
  assert_equal('b', o)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miga-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.20.10
4
+ version: 1.3.20.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luis M. Rodriguez-R
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-12 00:00:00.000000000 Z
11
+ date: 2024-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: daemons