miga-base 0.7.16.10 → 0.7.19.0
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 +4 -4
- data/lib/miga/cli/action/doctor/base.rb +11 -31
- data/lib/miga/cli/action/lair.rb +12 -5
- data/lib/miga/cli/action/run.rb +1 -1
- data/lib/miga/cli/action/wf.rb +1 -1
- data/lib/miga/common.rb +6 -3
- data/lib/miga/common/with_daemon.rb +1 -1
- data/lib/miga/daemon.rb +19 -8
- data/lib/miga/daemon/base.rb +7 -1
- data/lib/miga/dataset.rb +7 -3
- data/lib/miga/dataset/result.rb +10 -5
- data/lib/miga/lair.rb +4 -2
- data/lib/miga/sqlite.rb +49 -0
- data/lib/miga/version.rb +2 -2
- data/scripts/maintenance.bash +9 -0
- data/scripts/miga.bash +8 -8
- data/scripts/project_stats.bash +3 -0
- data/test/daemon_test.rb +21 -3
- data/utils/cleanup-databases.rb +8 -10
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc5df224531c2f5e902304b478aabe0ba18c02b836c5bab66a675257a3739a08
|
4
|
+
data.tar.gz: 438b9f2cefad3ecc3b65e17f81d5708f6a589c8b34f22b63235cf4123a156922
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 506dd5c19259071abd5cf0a130a70557967833edc520fada73030372d7736f2fe114ce4879bc224e37bcbe407a566bbd3cef39a5bc8ec9669c9c4cd1e63edb74
|
7
|
+
data.tar.gz: 4edb685f9a4adb69339e5ef477d4a0a332da606b402d380e3eab77a055ab94582be3be90f904e9403bc20d3f81c3753ed85df8a43bd9afc3e97b41f88cfd9fb1
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'miga/cli/action'
|
2
|
-
require '
|
2
|
+
require 'miga/sqlite'
|
3
3
|
|
4
4
|
class MiGA::Cli::Action::Doctor < MiGA::Cli::Action
|
5
5
|
end
|
@@ -10,9 +10,7 @@ module MiGA::Cli::Action::Doctor::Base
|
|
10
10
|
# tables saving +metric+ (:ani or :aai) and call +blk+ if the
|
11
11
|
# file is corrupt or doesn't contain the expected structure
|
12
12
|
def check_sqlite3_database(db_file, metric, &blk)
|
13
|
-
|
14
|
-
conn.execute("select count(*) from #{metric}").first
|
15
|
-
end
|
13
|
+
MiGA::SQLite.new(db_file).run("select count(*) from #{metric}")
|
16
14
|
rescue SQLite3::SQLException, SQLite3::CorruptException
|
17
15
|
blk.call
|
18
16
|
end
|
@@ -107,11 +105,7 @@ module MiGA::Cli::Action::Doctor::Base
|
|
107
105
|
dist = dataset.result(:distances) or return
|
108
106
|
path = dist.file_path(:aai_db) or return
|
109
107
|
|
110
|
-
|
111
|
-
SQLite3::Database.new(path) do |conn|
|
112
|
-
o = conn.execute('select seq2 from aai').map(&:first)
|
113
|
-
end
|
114
|
-
o
|
108
|
+
MiGA::SQLite.new(path).run('select seq2 from aai').map(&:first)
|
115
109
|
end
|
116
110
|
|
117
111
|
##
|
@@ -120,34 +114,20 @@ module MiGA::Cli::Action::Doctor::Base
|
|
120
114
|
def save_bidirectional(a, b)
|
121
115
|
each_database_file(a) do |db_file, metric, result|
|
122
116
|
data = nil
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
"from #{metric} where seq2 = ? limit 1", b.name
|
128
|
-
).first
|
129
|
-
end
|
117
|
+
data = MiGA::SQLite.new(db_file).run(
|
118
|
+
"select seq1, seq2, #{metric}, sd, n, omega " +
|
119
|
+
"from #{metric} where seq2 = ? limit 1", b.name
|
120
|
+
).first
|
130
121
|
next if data.nil? || data.empty?
|
131
122
|
|
132
123
|
db_file_b = File.join(File.dirname(db_file), "#{b.name}.db")
|
133
124
|
next unless File.exist?(db_file_b)
|
134
125
|
|
135
126
|
data[0], data[1] = data[1], data[0]
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
conn.execute(
|
141
|
-
"insert into #{metric} (seq1, seq2, #{metric}, sd, n, omega) " +
|
142
|
-
"values(?, ?, ?, ?, ?, ?)", data
|
143
|
-
)
|
144
|
-
rescue SQLite3::BusyException => e
|
145
|
-
raise "Cannot populate #{db_file_b}: #{e.message}" if attempts > 3
|
146
|
-
|
147
|
-
sleep(1)
|
148
|
-
retry
|
149
|
-
end
|
150
|
-
end
|
127
|
+
MiGA::SQLite.new(db_file_b).run(
|
128
|
+
"insert into #{metric} (seq1, seq2, #{metric}, sd, n, omega) " +
|
129
|
+
"values(?, ?, ?, ?, ?, ?)", data
|
130
|
+
)
|
151
131
|
end
|
152
132
|
end
|
153
133
|
end
|
data/lib/miga/cli/action/lair.rb
CHANGED
@@ -25,6 +25,10 @@ class MiGA::Cli::Action::Lair < MiGA::Cli::Action
|
|
25
25
|
'-p', '--path PATH',
|
26
26
|
'(Mandatory) Path to the directory where the MiGA projects are located'
|
27
27
|
) { |v| cli[:path] = v }
|
28
|
+
opt.on(
|
29
|
+
'--exclude NAME1,NAME2,NAME3', Array,
|
30
|
+
'Exclude these projects (identified by name) from the lair'
|
31
|
+
) { |v| cli[:exclude] = v }
|
28
32
|
opt.on(
|
29
33
|
'--json PATH',
|
30
34
|
'Path to a custom daemon definition in json format'
|
@@ -80,19 +84,22 @@ class MiGA::Cli::Action::Lair < MiGA::Cli::Action
|
|
80
84
|
|
81
85
|
def perform
|
82
86
|
cli.ensure_par(path: '-p')
|
87
|
+
k_opts = %i[
|
88
|
+
json latency wait_for keep_inactive trust_timestamp name dry exclude
|
89
|
+
]
|
90
|
+
opts = Hash[k_opts.map { |k| [k, cli[k]] }]
|
91
|
+
lair = MiGA::Lair.new(cli[:path], opts)
|
92
|
+
|
83
93
|
case cli.operation.to_sym
|
84
94
|
when :terminate
|
85
|
-
|
95
|
+
lair.terminate_daemons
|
86
96
|
when :list
|
87
97
|
o = []
|
88
|
-
|
98
|
+
lair.each_daemon do |d|
|
89
99
|
o << [d.daemon_name, d.class, d.daemon_home, d.active?, d.last_alive]
|
90
100
|
end
|
91
101
|
cli.table(%w[name class path active last_alive], o)
|
92
102
|
else
|
93
|
-
k_opts = %i[json latency wait_for keep_inactive trust_timestamp name dry]
|
94
|
-
opts = Hash[k_opts.map { |k| [k, cli[k]] }]
|
95
|
-
lair = MiGA::Lair.new(cli[:path], opts)
|
96
103
|
lair.daemon(cli.operation, cli[:daemon_opts])
|
97
104
|
end
|
98
105
|
end
|
data/lib/miga/cli/action/run.rb
CHANGED
@@ -59,7 +59,7 @@ class MiGA::Cli::Action::Run < MiGA::Cli::Action
|
|
59
59
|
"MIGA=#{miga.shellescape}", "CORES=#{cli[:thr]}"]
|
60
60
|
obj = cli.load_project_or_dataset
|
61
61
|
klass = obj.class
|
62
|
-
virtual_task = [
|
62
|
+
virtual_task = %i[p d maintenance].include?(cli[:result])
|
63
63
|
cmd << "DATASET=#{obj.name.shellescape}" if obj.is_a? MiGA::Dataset
|
64
64
|
if klass.RESULT_DIRS[cli[:result]].nil? and not virtual_task
|
65
65
|
raise "Unsupported #{klass.to_s.sub(/.*::/, '')} result: #{cli[:result]}."
|
data/lib/miga/cli/action/wf.rb
CHANGED
@@ -184,7 +184,7 @@ module MiGA::Cli::Action::Wf
|
|
184
184
|
def call_cli(cmd)
|
185
185
|
cmd << '-v' if cli[:verbose]
|
186
186
|
MiGA::MiGA.DEBUG "Cli::Action::Wf.call_cli #{cmd}"
|
187
|
-
MiGA::Cli.new(cmd.map(&:to_s)).launch
|
187
|
+
MiGA::Cli.new(cmd.map(&:to_s)).launch(true)
|
188
188
|
end
|
189
189
|
|
190
190
|
def run_daemon
|
data/lib/miga/common.rb
CHANGED
@@ -74,10 +74,13 @@ class MiGA::MiGA
|
|
74
74
|
@_advance_time[:n] = n
|
75
75
|
|
76
76
|
# Report
|
77
|
-
adv_vals = [100.0 * n / total, num_suffix(n, bin), num_suffix(total, bin)]
|
78
77
|
adv =
|
79
|
-
total.nil?
|
80
|
-
('
|
78
|
+
if total.nil?
|
79
|
+
(n == 0 ? '' : num_suffix(n, bin))
|
80
|
+
else
|
81
|
+
vals = [100.0 * n / total, num_suffix(n, bin), num_suffix(total, bin)]
|
82
|
+
('%.1f%% (%s/%s)' % vals)
|
83
|
+
end
|
81
84
|
left =
|
82
85
|
if @_advance_time[:avg].nil?
|
83
86
|
''
|
@@ -158,7 +158,7 @@ module MiGA::Common::WithDaemon
|
|
158
158
|
# Returns the status of the daemon with +opts+
|
159
159
|
def status(opts = [], wait = true)
|
160
160
|
if active?
|
161
|
-
say "Running with pid #{File.read(pid_file)}"
|
161
|
+
say "Running with pid #{File.size?(pid_file) ? File.read(pid_file) : '?'}"
|
162
162
|
else
|
163
163
|
say 'Not running'
|
164
164
|
end
|
data/lib/miga/daemon.rb
CHANGED
@@ -73,7 +73,7 @@ class MiGA::Daemon < MiGA::MiGA
|
|
73
73
|
say 'MiGA:%s launched' % project.name
|
74
74
|
say '-----------------------------------'
|
75
75
|
miga_say "Saving log to: #{output_file}" unless show_log?
|
76
|
-
|
76
|
+
queue_maintenance
|
77
77
|
load_status
|
78
78
|
say 'Configuration options:'
|
79
79
|
say @runopts.to_s
|
@@ -92,8 +92,7 @@ class MiGA::Daemon < MiGA::MiGA
|
|
92
92
|
flush!
|
93
93
|
if (loop_i % 12).zero?
|
94
94
|
purge!
|
95
|
-
|
96
|
-
# recalculate_status!
|
95
|
+
queue_maintenance
|
97
96
|
end
|
98
97
|
save_status
|
99
98
|
sleep(latency)
|
@@ -101,9 +100,13 @@ class MiGA::Daemon < MiGA::MiGA
|
|
101
100
|
true
|
102
101
|
end
|
103
102
|
|
104
|
-
|
105
|
-
|
106
|
-
|
103
|
+
##
|
104
|
+
# Queue maintenance tasks as an analysis job
|
105
|
+
def queue_maintenance
|
106
|
+
return if bypass_maintenance?
|
107
|
+
|
108
|
+
say 'Queueing maintenance tasks'
|
109
|
+
queue_job(:maintenance)
|
107
110
|
end
|
108
111
|
|
109
112
|
##
|
@@ -179,6 +182,7 @@ class MiGA::Daemon < MiGA::MiGA
|
|
179
182
|
unless show_log?
|
180
183
|
n = project.dataset_names.count
|
181
184
|
k = jobs_to_run.size + jobs_running.size
|
185
|
+
k -= 1 unless get_job(:maintenance).nil?
|
182
186
|
advance('Datasets:', n - k, n, false)
|
183
187
|
miga_say if k == 0
|
184
188
|
end
|
@@ -271,6 +275,11 @@ class MiGA::Daemon < MiGA::MiGA
|
|
271
275
|
# Avoid single datasets hogging resources
|
272
276
|
@jobs_to_run.rotate! rand(jobs_to_run.size)
|
273
277
|
|
278
|
+
# Prioritize: Project-wide > MiGA Online queries > Other datasets
|
279
|
+
@jobs_to_run.sort_by! do |job|
|
280
|
+
job[:ds].nil? ? 1 : job[:ds_name] =~ /^qG_/ ? 2 : 3
|
281
|
+
end
|
282
|
+
|
274
283
|
# Launch as many +jobs_to_run+ as possible
|
275
284
|
while (hostk = next_host)
|
276
285
|
break if jobs_to_run.empty?
|
@@ -309,11 +318,13 @@ class MiGA::Daemon < MiGA::MiGA
|
|
309
318
|
job[:hostk] = hostk
|
310
319
|
job[:cmd] = job[:cmd].miga_variables(host: nodelist[hostk])
|
311
320
|
job[:pid] = spawn job[:cmd]
|
312
|
-
|
321
|
+
MiGA::MiGA.DEBUG "Detaching PID: #{job[:pid]}"
|
322
|
+
Process.detach(job[:pid]) unless [nil, '', 0].include?(job[:pid])
|
313
323
|
when 'bash'
|
314
324
|
# Local job
|
315
325
|
job[:pid] = spawn job[:cmd]
|
316
|
-
|
326
|
+
MiGA::MiGA.DEBUG "Detaching PID: #{job[:pid]}"
|
327
|
+
Process.detach(job[:pid]) unless [nil, '', 0].include?(job[:pid])
|
317
328
|
else
|
318
329
|
# Schedule cluster job (qsub, msub, slurm)
|
319
330
|
job[:pid] = `#{job[:cmd]}`.chomp
|
data/lib/miga/daemon/base.rb
CHANGED
@@ -17,7 +17,7 @@ module MiGA::Daemon::Base
|
|
17
17
|
if !force && v == 0 && k != :verbosity
|
18
18
|
raise "Daemon's #{k} cannot be set to zero"
|
19
19
|
end
|
20
|
-
when :shutdown_when_done, :show_log
|
20
|
+
when :shutdown_when_done, :show_log, :bypass_maintenance
|
21
21
|
v = !!v
|
22
22
|
when :nodelist
|
23
23
|
if v =~ /^\$/
|
@@ -63,6 +63,12 @@ module MiGA::Daemon::Base
|
|
63
63
|
!!runopts(:shutdown_when_done)
|
64
64
|
end
|
65
65
|
|
66
|
+
##
|
67
|
+
# Should the daemon ignore regular maintenance steps?
|
68
|
+
def bypass_maintenance?
|
69
|
+
!!runopts(:bypass_maintenance)
|
70
|
+
end
|
71
|
+
|
66
72
|
##
|
67
73
|
# Returns the level of verbosity for the daemon as an Integer, or 1 if unset.
|
68
74
|
# Verbosity levels are:
|
data/lib/miga/dataset.rb
CHANGED
@@ -7,7 +7,11 @@ require 'miga/metadata'
|
|
7
7
|
require 'miga/dataset/result'
|
8
8
|
require 'miga/dataset/status'
|
9
9
|
require 'miga/dataset/hooks'
|
10
|
-
|
10
|
+
|
11
|
+
# This library is only required by +#closest_relatives+, so it is now
|
12
|
+
# being loaded on call instead to allow most of miga-base to work without
|
13
|
+
# issue in systems with problematic SQLite3 installations.
|
14
|
+
# require 'miga/sqlite'
|
11
15
|
|
12
16
|
##
|
13
17
|
# Dataset representation in MiGA
|
@@ -190,8 +194,8 @@ class MiGA::Dataset < MiGA::MiGA
|
|
190
194
|
r = result(ref_project ? :taxonomy : :distances)
|
191
195
|
return nil if r.nil?
|
192
196
|
|
193
|
-
|
194
|
-
|
197
|
+
require 'miga/sqlite'
|
198
|
+
MiGA::SQLite.new(r.file_path(:aai_db)).run(
|
195
199
|
'SELECT seq2, aai FROM aai WHERE seq2 != ? ' \
|
196
200
|
'GROUP BY seq2 ORDER BY aai DESC LIMIT ?', [name, how_many]
|
197
201
|
)
|
data/lib/miga/dataset/result.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
require 'sqlite3'
|
2
1
|
require 'miga/result'
|
3
2
|
require 'miga/dataset/base'
|
4
3
|
require 'miga/common/with_result'
|
5
4
|
|
5
|
+
# This library is only required by +#cleanup_distances!+, so it is now
|
6
|
+
# being loaded on call instead to allow most of miga-base to work without
|
7
|
+
# issue in systems with problematic SQLite3 installations.
|
8
|
+
# require 'miga/sqlite'
|
9
|
+
|
6
10
|
##
|
7
11
|
# Helper module including specific functions to add dataset results
|
8
12
|
module MiGA::Dataset::Result
|
@@ -144,20 +148,21 @@ module MiGA::Dataset::Result
|
|
144
148
|
# the project as reference datasets.
|
145
149
|
def cleanup_distances!
|
146
150
|
r = get_result(:distances)
|
147
|
-
ref = project.datasets.select(&:ref?).select(&:active?).map(&:name)
|
148
151
|
return if r.nil?
|
149
152
|
|
153
|
+
require 'miga/sqlite'
|
154
|
+
ref = project.datasets.select(&:ref?).select(&:active?).map(&:name)
|
150
155
|
%i[haai_db aai_db ani_db].each do |db_type|
|
151
156
|
db = r.file_path(db_type)
|
152
157
|
next if db.nil? || !File.size?(db)
|
153
158
|
|
154
|
-
sqlite_db =
|
159
|
+
sqlite_db = MiGA::SQLite.new(db)
|
155
160
|
table = db_type[-6..-4]
|
156
|
-
val = sqlite_db.
|
161
|
+
val = sqlite_db.run("select seq2 from #{table}")
|
157
162
|
next if val.empty?
|
158
163
|
|
159
164
|
(val.map(&:first) - ref).each do |extra|
|
160
|
-
sqlite_db.
|
165
|
+
sqlite_db.run("delete from #{table} where seq2=?", extra)
|
161
166
|
end
|
162
167
|
end
|
163
168
|
end
|
data/lib/miga/lair.rb
CHANGED
@@ -31,6 +31,7 @@ class MiGA::Lair < MiGA::MiGA
|
|
31
31
|
# by default: true
|
32
32
|
# - dry: Only report when daemons would be launched, but don't actually launch
|
33
33
|
# them
|
34
|
+
# - exclude: Array of project names to be excluded from the lair
|
34
35
|
def initialize(path, opts = {})
|
35
36
|
@path = File.expand_path(path)
|
36
37
|
@options = opts
|
@@ -41,7 +42,8 @@ class MiGA::Lair < MiGA::MiGA
|
|
41
42
|
keep_inactive: false,
|
42
43
|
trust_timestamp: true,
|
43
44
|
name: File.basename(@path),
|
44
|
-
dry: false
|
45
|
+
dry: false,
|
46
|
+
exclude: []
|
45
47
|
}.each { |k, v| @options[k] = v if @options[k].nil? }
|
46
48
|
end
|
47
49
|
|
@@ -109,7 +111,7 @@ class MiGA::Lair < MiGA::MiGA
|
|
109
111
|
project = MiGA::Project.load(f)
|
110
112
|
raise "Cannot load project: #{f}" if project.nil?
|
111
113
|
|
112
|
-
yield(project)
|
114
|
+
yield(project) unless options[:exclude].include?(project.name)
|
113
115
|
elsif Dir.exist? f
|
114
116
|
each_project(f) { |p| yield(p) }
|
115
117
|
end
|
data/lib/miga/sqlite.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# @package MiGA
|
2
|
+
# @license Artistic-2.0
|
3
|
+
|
4
|
+
require 'sqlite3'
|
5
|
+
|
6
|
+
##
|
7
|
+
# SQLite3 wrapper for MiGA.
|
8
|
+
class MiGA::SQLite < MiGA::MiGA
|
9
|
+
class << self
|
10
|
+
##
|
11
|
+
# Default parsing options. Supported +opts+ keys:
|
12
|
+
# - +:busy_attempts+: Number of times to retry when database is busy
|
13
|
+
# (default: 3)
|
14
|
+
def default_opts(opts = {})
|
15
|
+
opts[:busy_attempts] ||= 3
|
16
|
+
opts
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Options hash
|
22
|
+
attr :opts
|
23
|
+
|
24
|
+
##
|
25
|
+
# Database absolute path
|
26
|
+
attr :path
|
27
|
+
|
28
|
+
##
|
29
|
+
# Create MiGA::SQLite with database in +path+ (without opening a connection)
|
30
|
+
# and options +opts+ (see +.default_opts+)
|
31
|
+
def initialize(path, opts = {})
|
32
|
+
@opts = MiGA::SQLite.default_opts(opts)
|
33
|
+
@path = File.absolute_path(path)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Executes +cmd+ and returns the result
|
38
|
+
def run(*cmd)
|
39
|
+
busy_attempts ||= 0
|
40
|
+
conn = SQLite3::Database.new(path)
|
41
|
+
conn.execute(*cmd)
|
42
|
+
rescue SQLite3::BusyException => e
|
43
|
+
busy_attempts += 1
|
44
|
+
raise "Database busy #{path}: #{e.message}" if busy_attempts >= 3
|
45
|
+
|
46
|
+
sleep(1)
|
47
|
+
retry
|
48
|
+
end
|
49
|
+
end
|
data/lib/miga/version.rb
CHANGED
@@ -8,7 +8,7 @@ module MiGA
|
|
8
8
|
# - Float representing the major.minor version.
|
9
9
|
# - Integer representing gem releases of the current version.
|
10
10
|
# - Integer representing minor changes that require new version number.
|
11
|
-
VERSION = [0.7,
|
11
|
+
VERSION = [0.7, 19, 0]
|
12
12
|
|
13
13
|
##
|
14
14
|
# Nickname for the current major.minor version.
|
@@ -16,7 +16,7 @@ module MiGA
|
|
16
16
|
|
17
17
|
##
|
18
18
|
# Date of the current gem release.
|
19
|
-
VERSION_DATE = Date.new(
|
19
|
+
VERSION_DATE = Date.new(2021, 1, 2)
|
20
20
|
|
21
21
|
##
|
22
22
|
# Reference of MiGA.
|
data/scripts/miga.bash
CHANGED
@@ -11,17 +11,17 @@ function exists { [[ -e "$1" ]] ; }
|
|
11
11
|
function fx_exists { [[ $(type -t "$1") == "function" ]] ; }
|
12
12
|
|
13
13
|
if [[ "$SCRIPT" != "d" && "$SCRIPT" != "p" ]] ; then
|
14
|
-
echo
|
15
|
-
echo
|
16
|
-
echo "
|
17
|
-
echo "
|
18
|
-
echo "
|
19
|
-
echo "Project: $PROJECT"
|
14
|
+
echo ""
|
15
|
+
echo "######[ $SCRIPT ]######"
|
16
|
+
echo "# Date: $(miga date)"
|
17
|
+
echo "# Host: $(hostname)"
|
18
|
+
echo "# MiGA: $MIGA"
|
19
|
+
echo "# Project: $PROJECT"
|
20
20
|
if [[ -n $DATASET ]] ; then
|
21
|
-
echo "Dataset: $DATASET"
|
21
|
+
echo "# Dataset: $DATASET"
|
22
22
|
miga edit -P "$PROJECT" -D "$DATASET" -m "_step=$SCRIPT"
|
23
23
|
fi
|
24
|
-
echo '
|
24
|
+
echo '#------------'
|
25
25
|
fi
|
26
26
|
|
27
27
|
true
|
data/scripts/project_stats.bash
CHANGED
@@ -12,12 +12,15 @@ cd "$DIR"
|
|
12
12
|
miga date > "miga-project.start"
|
13
13
|
|
14
14
|
# Execute doctor
|
15
|
+
echo "# Doctor"
|
15
16
|
miga doctor -P "$PROJECT" -t "$CORES" -v
|
16
17
|
|
17
18
|
# Index taxonomy
|
19
|
+
echo "# Index taxonomy"
|
18
20
|
miga tax_index -P "$PROJECT" -i "miga-project.taxonomy.json" --ref --active
|
19
21
|
|
20
22
|
# Index metadata
|
23
|
+
echo "# Index metadata"
|
21
24
|
ruby -I "$MIGA/lib" \
|
22
25
|
"$MIGA/utils/index_metadata.rb" "$PROJECT" "miga-project.metadata.db"
|
23
26
|
|
data/test/daemon_test.rb
CHANGED
@@ -93,7 +93,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
93
93
|
0 => /-{20}\n/,
|
94
94
|
1 => /MiGA:#{p.name} launched/,
|
95
95
|
2 => /-{20}\n/,
|
96
|
-
|
96
|
+
8 => /Probing running jobs\n/
|
97
97
|
}.each { |k, v| assert_match(v, l[k], "unexpected line: #{k}") }
|
98
98
|
ensure
|
99
99
|
begin
|
@@ -160,8 +160,9 @@ class DaemonTest < Test::Unit::TestCase
|
|
160
160
|
assert_equal(0, d1.jobs_running.size)
|
161
161
|
assert_equal(0, d1.jobs_to_run.size)
|
162
162
|
capture_stderr { d1.in_loop }
|
163
|
+
# 3 dataset jobs + 1 maintenance job:
|
163
164
|
assert_equal(1, d1.jobs_running.size)
|
164
|
-
assert_equal(
|
165
|
+
assert_equal(3, d1.jobs_to_run.size)
|
165
166
|
end
|
166
167
|
|
167
168
|
def test_maxjobs_runopts
|
@@ -172,7 +173,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
172
173
|
assert_equal(0, d1.jobs_to_run.size)
|
173
174
|
capture_stderr { d1.in_loop }
|
174
175
|
assert_equal(2, d1.jobs_running.size)
|
175
|
-
assert_equal(
|
176
|
+
assert_equal(2, d1.jobs_to_run.size)
|
176
177
|
end
|
177
178
|
|
178
179
|
def test_load_status
|
@@ -232,6 +233,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
232
233
|
end
|
233
234
|
|
234
235
|
def test_shutdown_when_done
|
236
|
+
daemon.runopts(:bypass_maintenance, true)
|
235
237
|
daemon.runopts(:shutdown_when_done, true)
|
236
238
|
out = capture_stderr { assert { !daemon.in_loop } }.string
|
237
239
|
assert_match(/Nothing else to do/, out)
|
@@ -317,4 +319,20 @@ class DaemonTest < Test::Unit::TestCase
|
|
317
319
|
out = capture_stderr { d1.in_loop }.string
|
318
320
|
assert_match(/Daemon loop start/, out)
|
319
321
|
end
|
322
|
+
|
323
|
+
def test_bypass_maintenance
|
324
|
+
# Default (run maintenance)
|
325
|
+
d = daemon(0)
|
326
|
+
d.runopts(:latency, 0, true)
|
327
|
+
capture_stderr { d.in_loop }
|
328
|
+
assert_equal(1, d.jobs_running.size)
|
329
|
+
assert_equal(:maintenance, d.jobs_running.first[:job])
|
330
|
+
|
331
|
+
# Bypassing maintenance
|
332
|
+
d = daemon(1)
|
333
|
+
d.runopts(:latency, 0, true)
|
334
|
+
d.runopts(:bypass_maintenance, true)
|
335
|
+
capture_stderr { d.in_loop }
|
336
|
+
assert_equal([], d.jobs_running)
|
337
|
+
end
|
320
338
|
end
|
data/utils/cleanup-databases.rb
CHANGED
@@ -5,21 +5,17 @@ require 'miga'
|
|
5
5
|
|
6
6
|
ARGV[1] or abort "Usage: #{$0} path/to/project threads"
|
7
7
|
|
8
|
-
$stderr.puts 'Cleaning databases...'
|
9
8
|
p = MiGA::Project.load(ARGV[0])
|
10
|
-
|
9
|
+
dsn = p.dataset_names
|
11
10
|
thr = ARGV[1].to_i
|
12
11
|
|
13
|
-
|
14
|
-
|
12
|
+
m = MiGA::MiGA.new
|
13
|
+
m.say 'Cleaning Databases'
|
15
14
|
|
16
15
|
(0..thr - 1).each do |t|
|
17
16
|
fork do
|
18
|
-
|
19
|
-
|
20
|
-
$stderr.print '#'
|
21
|
-
pc.shift
|
22
|
-
end
|
17
|
+
dsn.each_with_index do |i, idx|
|
18
|
+
m.advance('Dataset:', dsn.size, idx + 1) if t == 0
|
23
19
|
next unless (idx % thr) == t
|
24
20
|
|
25
21
|
d = p.dataset(i)
|
@@ -30,4 +26,6 @@ $stderr.puts (('.' * 9 + '|') * 10) + ' 100%'
|
|
30
26
|
end
|
31
27
|
end
|
32
28
|
Process.waitall
|
33
|
-
|
29
|
+
m.advance('Dataset:', dsn.size, dsn.size)
|
30
|
+
m.say
|
31
|
+
|
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: 0.7.
|
4
|
+
version: 0.7.19.0
|
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:
|
11
|
+
date: 2021-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: daemons
|
@@ -196,6 +196,7 @@ files:
|
|
196
196
|
- lib/miga/result/dates.rb
|
197
197
|
- lib/miga/result/source.rb
|
198
198
|
- lib/miga/result/stats.rb
|
199
|
+
- lib/miga/sqlite.rb
|
199
200
|
- lib/miga/tax_dist.rb
|
200
201
|
- lib/miga/tax_index.rb
|
201
202
|
- lib/miga/taxonomy.rb
|
@@ -211,6 +212,7 @@ files:
|
|
211
212
|
- scripts/essential_genes.bash
|
212
213
|
- scripts/haai_distances.bash
|
213
214
|
- scripts/init.bash
|
215
|
+
- scripts/maintenance.bash
|
214
216
|
- scripts/miga.bash
|
215
217
|
- scripts/mytaxa.bash
|
216
218
|
- scripts/mytaxa_scan.bash
|