miga-base 0.6.3.2 → 0.6.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|