miga-base 0.6.3.2 → 0.6.4.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.rb +1 -3
- data/lib/miga/cli/action/lair.rb +81 -0
- data/lib/miga/cli/base.rb +1 -0
- data/lib/miga/common.rb +10 -0
- data/lib/miga/lair.rb +153 -0
- data/lib/miga/version.rb +2 -2
- 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: 56e28b1948d83d30fcfbb1bb1925875996d4c23dd6f707ae1f11198ae4fe598f
|
4
|
+
data.tar.gz: d1285c61c990a597f9ed65ba298467c7ea4aac49441af91e2711a5590fa8f05b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '021513891f1a58f8d518a77691aa89da856741bd7627454a2763b9c825b354ba14f712b7ff9a37b584629bb17ce04eec8a147c5ea2d4511a6a62d556b2a567fc'
|
7
|
+
data.tar.gz: 62898b0497e07db953534a24b40f9df1b76ba2304676a2c4763599be0ae8d03c7fa36e1a7d580745f04074c27d53f808dd1e8842f9bccda9641b01c76fda383b
|
data/lib/miga/cli.rb
CHANGED
@@ -106,9 +106,7 @@ class MiGA::Cli < MiGA::MiGA
|
|
106
106
|
# otherwise it's sent to +$stderr+
|
107
107
|
def say(*par)
|
108
108
|
return unless self[:verbose]
|
109
|
-
par
|
110
|
-
io = par.first.is_a?(IO) ? par.shift : $stderr
|
111
|
-
io.puts(*par)
|
109
|
+
super(*par)
|
112
110
|
end
|
113
111
|
|
114
112
|
##
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# @package MiGA
|
2
|
+
# @license Artistic-2.0
|
3
|
+
|
4
|
+
require 'miga/cli/action'
|
5
|
+
require 'miga/lair'
|
6
|
+
|
7
|
+
class MiGA::Cli::Action::Lair < MiGA::Cli::Action
|
8
|
+
|
9
|
+
def parse_cli
|
10
|
+
cli.defaults = { daemon_opts: [] }
|
11
|
+
cli.expect_operation = true
|
12
|
+
cli.parse do |opt|
|
13
|
+
opt.separator 'Available operations:'
|
14
|
+
{ start: 'Start an instance of the application.',
|
15
|
+
stop: 'Start an instance of the application.',
|
16
|
+
restart: 'Stop all instances and restart them afterwards.',
|
17
|
+
reload: 'Send a SIGHUP to all instances of the application.',
|
18
|
+
run: 'Start the application and stay on top.',
|
19
|
+
zap: 'Set the application to a stopped state.',
|
20
|
+
status: 'Show status (PID) of application instances.'
|
21
|
+
}.each { |k,v| opt.separator sprintf ' %*s%s', -33, k, v }
|
22
|
+
opt.separator ''
|
23
|
+
|
24
|
+
opt.separator 'MiGA options:'
|
25
|
+
opt.on(
|
26
|
+
'-p', '--path PATH',
|
27
|
+
'(Mandatory) Path to the directory where the MiGA projects are located'
|
28
|
+
) { |v| cli[:path] = v }
|
29
|
+
opt.on(
|
30
|
+
'--latency INT', Integer,
|
31
|
+
'Time to wait between iterations in seconds, by default: 120'
|
32
|
+
) { |v| cli[:latency] = v }
|
33
|
+
opt.on(
|
34
|
+
'--wait-for INT', Integer,
|
35
|
+
'Time to wait for a daemon to report being alive in seconds',
|
36
|
+
'by default: 900'
|
37
|
+
) { |v| cli[:wait_for] = v }
|
38
|
+
opt.on(
|
39
|
+
'--keep-inactive',
|
40
|
+
'If set, daemons are kept alive even when inactive;',
|
41
|
+
'i.e., when all tasks are complete'
|
42
|
+
) { |v| cli[:keep_inactive] = v }
|
43
|
+
opt.on(
|
44
|
+
'--name STRING',
|
45
|
+
'A name for the chief daemon process'
|
46
|
+
) { |v| cli[:name] = v }
|
47
|
+
opt.on(
|
48
|
+
'--json PATH',
|
49
|
+
'Path to a custom daemon definition in json format'
|
50
|
+
) { |v| cli[:json] = v }
|
51
|
+
cli.opt_common(opt)
|
52
|
+
|
53
|
+
opt.separator 'Daemon options:'
|
54
|
+
opt.on(
|
55
|
+
'-t', '--ontop',
|
56
|
+
'Stay on top (does not daemonize)'
|
57
|
+
) { cli[:daemon_opts] << '-t' }
|
58
|
+
opt.on(
|
59
|
+
'-f', '--force',
|
60
|
+
'Force operation'
|
61
|
+
) { cli[:daemon_opts] << '-f' }
|
62
|
+
opt.on(
|
63
|
+
'-n', '--no_wait',
|
64
|
+
'Do not wait for processes to stop'
|
65
|
+
) { cli[:daemon_opts] << '-n' }
|
66
|
+
opt.on(
|
67
|
+
'--shush',
|
68
|
+
'Silence the daemon'
|
69
|
+
) { cli[:daemon_opts] << '--shush' }
|
70
|
+
opt.separator ''
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def perform
|
75
|
+
cli.ensure_par(path: '-p')
|
76
|
+
k_opts = %i[latency wait_for keep_inactive name json]
|
77
|
+
opts = Hash[k_opts.map { |k| [k, cli[k]] }]
|
78
|
+
lair = MiGA::Lair.new(cli[:path], opts)
|
79
|
+
lair.daemon(cli.operation, cli[:daemon_opts])
|
80
|
+
end
|
81
|
+
end
|
data/lib/miga/cli/base.rb
CHANGED
@@ -37,6 +37,7 @@ module MiGA::Cli::Base
|
|
37
37
|
# System
|
38
38
|
init: 'Initialize MiGA to process new projects',
|
39
39
|
daemon: 'Controls the daemon of a MiGA project',
|
40
|
+
lair: 'Controls groups of daemons for several MiGA projects',
|
40
41
|
date: 'Returns the current date in standard MiGA format',
|
41
42
|
console: 'Opens an IRB console with MiGA',
|
42
43
|
# Taxonomy
|
data/lib/miga/common.rb
CHANGED
@@ -36,5 +36,15 @@ class MiGA::MiGA
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
##
|
40
|
+
# Print +par+ ensuring new line at the end.
|
41
|
+
# Date/time-stamp each line.
|
42
|
+
# If the first parameter is +IO+, the output is sent there,
|
43
|
+
# otherwise it's sent to +$stderr+
|
44
|
+
def say(*par)
|
45
|
+
io = par.first.is_a?(IO) ? par.shift : $stderr
|
46
|
+
io.puts(*par.map { |i| "[#{Time.now}] #{i}" })
|
47
|
+
end
|
48
|
+
|
39
49
|
end
|
40
50
|
|
data/lib/miga/lair.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# @package MiGA
|
2
|
+
# @license Artistic-2.0
|
3
|
+
|
4
|
+
require 'daemons'
|
5
|
+
require 'miga/daemon'
|
6
|
+
|
7
|
+
##
|
8
|
+
# Lair of MiGA Daemons handling job submissions
|
9
|
+
class MiGA::Lair < MiGA::MiGA
|
10
|
+
##
|
11
|
+
# When was the last time the chief daemon in this lair was seen active?
|
12
|
+
# Returns Time
|
13
|
+
def self.last_alive(path)
|
14
|
+
f = File.expand_path('.lair-alive', path)
|
15
|
+
return nil unless File.exist? f
|
16
|
+
Time.parse(File.read(f))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Absolute path to the directory where the projects are located
|
20
|
+
attr_reader :path
|
21
|
+
|
22
|
+
# Options used to setup the chief daemon
|
23
|
+
attr_accessor :options
|
24
|
+
|
25
|
+
# Integer indicating the current iteration
|
26
|
+
attr_reader :loop_i
|
27
|
+
|
28
|
+
##
|
29
|
+
# Initialize an inactive daemon for the directory at +path+. See #daemon
|
30
|
+
# to wake the chief daemon. Supported options include:
|
31
|
+
# - json: json definition for all children daemons, by default: nil
|
32
|
+
# - latency: time to wait between iterations in seconds, by default: 120
|
33
|
+
# - wait_for: time to wait for a daemon to report being alive in seconds,
|
34
|
+
# by default: 900
|
35
|
+
# - keep_inactive: boolean indicating if daemons should stay alive even when
|
36
|
+
# inactive (when all tasks are complete), by default: false
|
37
|
+
# - name: A name for the chief daemon process, by default: basename of +path+
|
38
|
+
def initialize(path, opts = {})
|
39
|
+
@path = File.expand_path(path)
|
40
|
+
@options = opts
|
41
|
+
@loop_i = -1
|
42
|
+
{
|
43
|
+
json: nil,
|
44
|
+
latency: 120,
|
45
|
+
wait_for: 900,
|
46
|
+
keep_inactive: false,
|
47
|
+
name: File.basename(@path)
|
48
|
+
}.each { |k, v| @options[k] = v if @options[k].nil? }
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# When was the last time the chief daemon for was seen active here?
|
53
|
+
# Returns Time.
|
54
|
+
def last_alive
|
55
|
+
MiGA::Lair.last_alive path
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Returns Hash containing the default options for the daemon.
|
60
|
+
def default_options
|
61
|
+
{ dir_mode: :normal, dir: path, multiple: false, log_output: true }
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Launches the +task+ with options +opts+ (as command-line arguments) and
|
66
|
+
# returns the process ID as an Integer. If +wait+ it waits for the process to
|
67
|
+
# complete, immediately returns otherwise.
|
68
|
+
# Supported tasks: start, stop, restart, status.
|
69
|
+
def daemon(task, opts = [], wait = true)
|
70
|
+
MiGA.DEBUG "Lair.daemon #{task} #{opts}"
|
71
|
+
config = default_options
|
72
|
+
opts.unshift(task.to_s)
|
73
|
+
config[:ARGV] = opts
|
74
|
+
# This additional degree of separation below was introduced so the Daemons
|
75
|
+
# package doesn't kill the parent process in workflows.
|
76
|
+
pid = fork do
|
77
|
+
Daemons.run_proc("MiGA:#{options[:name]}", config) { while in_loop; end }
|
78
|
+
end
|
79
|
+
Process.wait(pid) if wait
|
80
|
+
pid
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Tell the world that you're alive.
|
85
|
+
def declare_alive
|
86
|
+
File.open(File.join(path, '.lair-alive'), 'w') do |fh|
|
87
|
+
fh.print Time.now.to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Perform block for each project in the +dir+ directory,
|
93
|
+
# passing the absolute path of the project to the block.
|
94
|
+
# Searches for MiGA projects recursively in all
|
95
|
+
# subdirectories that are not MiGA projects.
|
96
|
+
def each_project(dir = path)
|
97
|
+
Dir.entries(dir) do |f|
|
98
|
+
f = File.join(dir, f)
|
99
|
+
if MiGA::Project.exists? f
|
100
|
+
yield(f)
|
101
|
+
elsif Dir.exists? f
|
102
|
+
each_project(f) { |p| yield(p) }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Traverse directories checking MiGA projects
|
109
|
+
def check_directories
|
110
|
+
each_project do |dir|
|
111
|
+
alive = MiGA::Daemon.last_alive(dir)
|
112
|
+
next if !alive.nil? && alive > Time.now - options[:wait_for]
|
113
|
+
launch_daemon(dir)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Launch daemon for the project stored in +dir+
|
119
|
+
def launch_daemon(dir)
|
120
|
+
project = MiGA::Project.load(dir)
|
121
|
+
raise "Cannot load project: #{dir}" if project.nil?
|
122
|
+
d = MiGA::Daemon.new(project, options[:json])
|
123
|
+
d.runopts(:shutdown_when_done, true) unless options[:keep_inactive]
|
124
|
+
say "Launching daemon: #{dir}"
|
125
|
+
d.daemon(:start, [], false)
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Run one loop step. Returns a Boolean indicating if the loop should continue.
|
130
|
+
def in_loop
|
131
|
+
declare_alive
|
132
|
+
if loop_i == -1
|
133
|
+
say '-----------------------------------'
|
134
|
+
say 'MiGA:%s launched' % options[:name]
|
135
|
+
say '-----------------------------------'
|
136
|
+
say 'Configuration options:'
|
137
|
+
say options.to_s
|
138
|
+
@loop_i = 0
|
139
|
+
end
|
140
|
+
@loop_i += 1
|
141
|
+
check_directories
|
142
|
+
sleep(options[:latency])
|
143
|
+
true
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Terminates a chief daemon
|
148
|
+
def terminate
|
149
|
+
say 'Terminating chief daemon...'
|
150
|
+
f = File.expand_path('.lair-alive', project.path)
|
151
|
+
File.unlink(f) if File.exist? f
|
152
|
+
end
|
153
|
+
end
|
data/lib/miga/version.rb
CHANGED
@@ -10,7 +10,7 @@ module MiGA
|
|
10
10
|
# - Float representing the major.minor version.
|
11
11
|
# - Integer representing gem releases of the current version.
|
12
12
|
# - Integer representing minor changes that require new version number.
|
13
|
-
VERSION = [0.6,
|
13
|
+
VERSION = [0.6, 4, 0]
|
14
14
|
|
15
15
|
##
|
16
16
|
# Nickname for the current major.minor version.
|
@@ -18,7 +18,7 @@ module MiGA
|
|
18
18
|
|
19
19
|
##
|
20
20
|
# Date of the current gem release.
|
21
|
-
VERSION_DATE = Date.new(2020, 4,
|
21
|
+
VERSION_DATE = Date.new(2020, 4, 15)
|
22
22
|
|
23
23
|
##
|
24
24
|
# Reference of MiGA.
|
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.6.
|
4
|
+
version: 0.6.4.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: 2020-04-
|
11
|
+
date: 2020-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: daemons
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- lib/miga/cli/action/index_wf.rb
|
134
134
|
- lib/miga/cli/action/init.rb
|
135
135
|
- lib/miga/cli/action/init/daemon_helper.rb
|
136
|
+
- lib/miga/cli/action/lair.rb
|
136
137
|
- lib/miga/cli/action/ln.rb
|
137
138
|
- lib/miga/cli/action/ls.rb
|
138
139
|
- lib/miga/cli/action/ncbi_get.rb
|
@@ -165,6 +166,7 @@ files:
|
|
165
166
|
- lib/miga/dataset/hooks.rb
|
166
167
|
- lib/miga/dataset/result.rb
|
167
168
|
- lib/miga/json.rb
|
169
|
+
- lib/miga/lair.rb
|
168
170
|
- lib/miga/metadata.rb
|
169
171
|
- lib/miga/project.rb
|
170
172
|
- lib/miga/project/base.rb
|