pampa 2.0.29 → 2.0.30
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pampa/app.rb +194 -0
- data/lib/pampa/dispatcher.rb +133 -0
- data/lib/pampa/worker.rb +172 -0
- data/lib/pampa.rb +42 -384
- data/pampa.gemspec +43 -0
- metadata +80 -17
- data/worker.rb +0 -147
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8610d7df9639c7fe8e09b420795dc61c0cdb76b4df04b04a935689bec1d3d5be
|
4
|
+
data.tar.gz: 2c9d0b02219822ca36091805ab2e71ea59285db83255da737acd84d23eda7414
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4500f05166c288b46cdce8f6c361cc9ca9a26314300b1e97248474ac2be432d863b2e34e0e3b24398c677910ef109ca0cbdeddf65d5fc387227560806966d784
|
7
|
+
data.tar.gz: e364de99b69c3c93b30fb59f69450a5e8637e91f36d8b810fb7eeb19b084c1686362841a48a1118aadc2fe347f31b0a3c2fc370754cbe536d941d1f770a2de4d
|
data/lib/pampa/app.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# MySaaS - Pampa Dashboard
|
2
|
+
# Copyright (C) 2022 ExpandedVenture, LLC.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# You may not use this file except in compliance with the License.
|
6
|
+
#
|
7
|
+
# Authors: Leandro Daniel Sardi (https://github.com/leandrosardi)
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'pampa'
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
#
|
14
|
+
PARSER = BlackStack::SimpleCommandLineParser.new(
|
15
|
+
:description => 'This command will launch a Sinatra-based Pampa dashboard.',
|
16
|
+
:configuration => [{
|
17
|
+
:name=>'port',
|
18
|
+
:mandatory=>false,
|
19
|
+
:description=>'Listening port. Default: 3000.',
|
20
|
+
:type=>BlackStack::SimpleCommandLineParser::INT,
|
21
|
+
:default => 3000,
|
22
|
+
}, {
|
23
|
+
:name=>'config',
|
24
|
+
:mandatory=>false,
|
25
|
+
:description=>'Configuration file. Default: "config.rb".',
|
26
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
27
|
+
:default => 'config.rb',
|
28
|
+
}, {
|
29
|
+
:name=>'db',
|
30
|
+
:mandatory=>false,
|
31
|
+
:default=>'postgres',
|
32
|
+
:description=>'Database driver. Supported values: postgres, crdb. Default: postgres.',
|
33
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
34
|
+
}, {
|
35
|
+
:name=>'log',
|
36
|
+
:mandatory=>false,
|
37
|
+
:default=>true,
|
38
|
+
:description=>'If write log in the file ./app.log or not. Default: "yes"',
|
39
|
+
:type=>BlackStack::SimpleCommandLineParser::BOOL,
|
40
|
+
}]
|
41
|
+
)
|
42
|
+
|
43
|
+
# create logger
|
44
|
+
l = PARSER.value('log') ? BlackStack::LocalLogger.new('app.log') : BlackStack::BaseLogger.new(nil)
|
45
|
+
|
46
|
+
#
|
47
|
+
# load config file
|
48
|
+
l.logs "Loading #{PARSER.value('config').to_s.blue}... "
|
49
|
+
require PARSER.value('config')
|
50
|
+
l.logf 'done'.green
|
51
|
+
|
52
|
+
l.logs 'Connecting to database... '
|
53
|
+
if PARSER.value('db') == 'postgres'
|
54
|
+
DB = BlackStack::PostgreSQL::connect
|
55
|
+
elsif PARSER.value('db') == 'crdb'
|
56
|
+
DB = BlackStack::CockroachDB::connect
|
57
|
+
else
|
58
|
+
raise 'Unknown database driver.'
|
59
|
+
end
|
60
|
+
l.logf 'done'.green
|
61
|
+
|
62
|
+
#
|
63
|
+
spec = Gem.loaded_specs['pampa']
|
64
|
+
puts '
|
65
|
+
_______ _______ __ __ _______ _______
|
66
|
+
| || _ || |_| || || _ |
|
67
|
+
| _ || |_| || || _ || |_| |
|
68
|
+
| |_| || || || |_| || |
|
69
|
+
| ___|| || || ___|| |
|
70
|
+
| | | _ || ||_|| || | | _ |
|
71
|
+
|___| |__| |__||_| |_||___| |__| |__|
|
72
|
+
|
73
|
+
Version: '+spec.version.to_s.green+'.
|
74
|
+
Authors: '+spec.authors.join(', ').green+'.
|
75
|
+
Documentation: '+spec.homepage.blue+'
|
76
|
+
|
77
|
+
Sandbox: '+ (BlackStack.sandbox? ? 'yes'.green : 'no'.yellow) +'
|
78
|
+
|
79
|
+
'
|
80
|
+
|
81
|
+
PORT = PARSER.value("port")
|
82
|
+
|
83
|
+
configure { set :server, :puma }
|
84
|
+
set :bind, '0.0.0.0'
|
85
|
+
set :port, PORT
|
86
|
+
enable :sessions
|
87
|
+
enable :static
|
88
|
+
|
89
|
+
configure do
|
90
|
+
enable :cross_origin
|
91
|
+
end
|
92
|
+
|
93
|
+
before do
|
94
|
+
headers 'Access-Control-Allow-Origin' => '*',
|
95
|
+
'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST']
|
96
|
+
end
|
97
|
+
|
98
|
+
set :protection, false
|
99
|
+
|
100
|
+
# Setting the root of views and public folders in the `~/code` folder in order to have access to extensions.
|
101
|
+
# reference: https://stackoverflow.com/questions/69028408/change-sinatra-views-directory-location
|
102
|
+
set :root, '.'
|
103
|
+
binding.pry
|
104
|
+
set :views, Gem.loaded_specs['pampa'].full_gem_path
|
105
|
+
|
106
|
+
# page not found redirection
|
107
|
+
not_found do
|
108
|
+
redirect '/404'
|
109
|
+
end
|
110
|
+
|
111
|
+
# unhandled exception redirectiopn
|
112
|
+
error do
|
113
|
+
max_lenght = 8000
|
114
|
+
s = "message=#{CGI.escape(env['sinatra.error'].to_s)}&"
|
115
|
+
s += "backtrace_size=#{CGI.escape(env['sinatra.error'].backtrace.size.to_s)}&"
|
116
|
+
i = 0
|
117
|
+
env['sinatra.error'].backtrace.each { |a|
|
118
|
+
a = "backtrace[#{i.to_s}]=#{CGI.escape(a.to_s)}&"
|
119
|
+
and_more = "backtrace[#{i.to_s}]=..."
|
120
|
+
if (s+a).size > max_lenght - and_more.size
|
121
|
+
s += and_more
|
122
|
+
break
|
123
|
+
else
|
124
|
+
s += a
|
125
|
+
end
|
126
|
+
i += 1
|
127
|
+
}
|
128
|
+
redirect "/500?#{s}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# condition: api_key parameter is required too for the access points
|
132
|
+
set(:api_key) do |*roles|
|
133
|
+
condition do
|
134
|
+
@return_message = {}
|
135
|
+
|
136
|
+
@return_message[:status] = 'success'
|
137
|
+
|
138
|
+
# validate: the pages using the :api_key condition must work as post only.
|
139
|
+
if request.request_method != 'POST'
|
140
|
+
@return_message[:status] = 'Pages with an `api_key` parameter are only available for POST requests.'
|
141
|
+
@return_message[:value] = ""
|
142
|
+
halt @return_message.to_json
|
143
|
+
end
|
144
|
+
|
145
|
+
@body = JSON.parse(request.body.read)
|
146
|
+
|
147
|
+
if !@body.has_key?('api_key')
|
148
|
+
# libero recursos
|
149
|
+
DB.disconnect
|
150
|
+
GC.start
|
151
|
+
@return_message[:status] = "api_key is required on #{@body.to_s}"
|
152
|
+
@return_message[:value] = ""
|
153
|
+
halt @return_message.to_json
|
154
|
+
end
|
155
|
+
|
156
|
+
if !@body['api_key'].guid?
|
157
|
+
# libero recursos
|
158
|
+
DB.disconnect
|
159
|
+
GC.start
|
160
|
+
|
161
|
+
@return_message[:status] = "Invalid api_key (#{@body['api_key']}))"
|
162
|
+
@return_message[:value] = ""
|
163
|
+
halt @return_message.to_json
|
164
|
+
end
|
165
|
+
|
166
|
+
validation_api_key = @body['api_key'].to_guid.downcase
|
167
|
+
|
168
|
+
if validation_api_key != API_KEY
|
169
|
+
# libero recursos
|
170
|
+
DB.disconnect
|
171
|
+
GC.start
|
172
|
+
#
|
173
|
+
@return_message[:status] = 'Wrong api_key'
|
174
|
+
@return_message[:value] = ""
|
175
|
+
halt @return_message.to_json
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
get '/404', :agent => /(.*)/ do
|
181
|
+
erb :'views/404', :layout => :'/views/layouts/public'
|
182
|
+
end
|
183
|
+
|
184
|
+
get '/500', :agent => /(.*)/ do
|
185
|
+
erb :'views/500', :layout => :'/views/layouts/public'
|
186
|
+
end
|
187
|
+
|
188
|
+
# dashboard
|
189
|
+
get '/', :agent => /(.*)/ do
|
190
|
+
redirect '/dashboard'
|
191
|
+
end
|
192
|
+
get '/dashboard', :agent => /(.*)/ do
|
193
|
+
erb :'views/dashboard' #, :layout => :'/views/layouts/public'
|
194
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# Pampa Dispatcher
|
2
|
+
# Copyright (C) 2022 ExpandedVenture, LLC.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# You may not use this file except in compliance with the License.
|
6
|
+
#
|
7
|
+
# Authors: Leandro Daniel Sardi (https://github.com/leandrosardi)
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'pampa'
|
11
|
+
|
12
|
+
# parse command line parameters
|
13
|
+
PARSER = BlackStack::SimpleCommandLineParser.new(
|
14
|
+
:description => 'This script starts an infinite loop. Each loop will look for a task to perform. Must be a delay between each loop.',
|
15
|
+
:configuration => [{
|
16
|
+
:name=>'delay',
|
17
|
+
:mandatory=>false,
|
18
|
+
:default=>10, # 5 minutes
|
19
|
+
:description=>'Minimum delay between loops. A minimum of 10 seconds is recommended, in order to don\'t hard the database server. Default is 30 seconds.',
|
20
|
+
:type=>BlackStack::SimpleCommandLineParser::INT,
|
21
|
+
}, {
|
22
|
+
:name=>'config',
|
23
|
+
:mandatory=>false,
|
24
|
+
:default=>'config.rb',
|
25
|
+
:description=>'Configuration file. Default: config.',
|
26
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
27
|
+
}, {
|
28
|
+
:name=>'db',
|
29
|
+
:mandatory=>false,
|
30
|
+
:default=>'postgres',
|
31
|
+
:description=>'Database driver. Supported values: postgres, crdb. Default: postgres.',
|
32
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
33
|
+
}, {
|
34
|
+
:name=>'log',
|
35
|
+
:mandatory=>false,
|
36
|
+
:default=>true,
|
37
|
+
:description=>'If write log in the file ./dispatcher.log or not. Default: "yes"',
|
38
|
+
:type=>BlackStack::SimpleCommandLineParser::BOOL,
|
39
|
+
}]
|
40
|
+
)
|
41
|
+
|
42
|
+
# create logger
|
43
|
+
l = PARSER.value('log') ? BlackStack::LocalLogger.new('dispatcher.log') : BlackStack::BaseLogger.new(nil)
|
44
|
+
|
45
|
+
# assign logger to pampa
|
46
|
+
BlackStack::Pampa.set_logger(l)
|
47
|
+
|
48
|
+
# load config file
|
49
|
+
l.logs "Loading #{PARSER.value('config').to_s.blue}... "
|
50
|
+
require PARSER.value('config')
|
51
|
+
l.logf 'done'.green
|
52
|
+
|
53
|
+
l.logs 'Connecting to database... '
|
54
|
+
if PARSER.value('db') == 'postgres'
|
55
|
+
DB = BlackStack::PostgreSQL::connect
|
56
|
+
elsif PARSER.value('db') == 'crdb'
|
57
|
+
DB = BlackStack::CockroachDB::connect
|
58
|
+
else
|
59
|
+
raise 'Unknown database driver.'
|
60
|
+
end
|
61
|
+
l.logf 'done'.green
|
62
|
+
|
63
|
+
# loop
|
64
|
+
begin
|
65
|
+
while true
|
66
|
+
# get the start loop time
|
67
|
+
l.logs 'Starting loop... '
|
68
|
+
start = Time.now()
|
69
|
+
l.logf 'done'.green
|
70
|
+
|
71
|
+
begin
|
72
|
+
# assign workers to each job
|
73
|
+
l.logs 'Stretching clusters... '
|
74
|
+
BlackStack::Pampa.stretch
|
75
|
+
l.logf 'done'.green
|
76
|
+
|
77
|
+
# relaunch expired tasks
|
78
|
+
l.logs 'Relaunching expired tasks... '
|
79
|
+
BlackStack::Pampa.relaunch
|
80
|
+
l.logf 'done'.green
|
81
|
+
|
82
|
+
# dispatch tasks to each worker
|
83
|
+
l.logs 'Dispatching tasks to workers... '
|
84
|
+
BlackStack::Pampa.dispatch
|
85
|
+
l.logf 'done'.green
|
86
|
+
|
87
|
+
# note: this catches the CTRL+C signal.
|
88
|
+
# note: this catches the `kill` command, ONLY if it has not the `-9` option.
|
89
|
+
rescue SignalException, SystemExit, Interrupt => e
|
90
|
+
l.logf 'Bye!'.yellow
|
91
|
+
raise e
|
92
|
+
rescue => e
|
93
|
+
l.logf "Error: #{e.to_console}".red
|
94
|
+
end
|
95
|
+
|
96
|
+
# release resource
|
97
|
+
l.logs 'Releasing resources... '
|
98
|
+
GC.start
|
99
|
+
DB.disconnect
|
100
|
+
l.logf 'done'.green
|
101
|
+
|
102
|
+
# get the end loop time
|
103
|
+
l.logs 'Ending loop... '
|
104
|
+
finish = Time.now()
|
105
|
+
l.logf 'done'.green
|
106
|
+
|
107
|
+
# get different in seconds between start and finish
|
108
|
+
# if diff > 30 seconds
|
109
|
+
l.logs 'Calculating loop duration... '
|
110
|
+
diff = finish - start
|
111
|
+
l.logf 'done'.green + " (#{diff.to_s.blue})"
|
112
|
+
|
113
|
+
if diff < PARSER.value('delay')
|
114
|
+
# sleep for 30 seconds
|
115
|
+
n = PARSER.value('delay')-diff
|
116
|
+
|
117
|
+
l.logs 'Sleeping for '+n.to_label+' seconds... '
|
118
|
+
sleep n
|
119
|
+
l.logf 'done'.green
|
120
|
+
else
|
121
|
+
l.log 'No sleeping. The loop took '+diff.to_label+' seconds.'
|
122
|
+
end
|
123
|
+
end # while true
|
124
|
+
rescue SignalException, SystemExit, Interrupt
|
125
|
+
# note: this catches the CTRL+C signal.
|
126
|
+
# note: this catches the `kill` command, ONLY if it has not the `-9` option.
|
127
|
+
l.logf 'Process Interrumpted.'.yellow
|
128
|
+
l.log 'Bye!'.yellow
|
129
|
+
rescue => e
|
130
|
+
l.logf "Fatal Error: #{e.to_console}".red
|
131
|
+
rescue
|
132
|
+
l.logf 'Unknown Fatal Error.'.red
|
133
|
+
end # begin
|
data/lib/pampa/worker.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
# MySaaS - Pampa Worker
|
2
|
+
# Copyright (C) 2022 ExpandedVenture, LLC.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# You may not use this file except in compliance with the License.
|
6
|
+
#
|
7
|
+
# Authors: Leandro Daniel Sardi (https://github.com/leandrosardi)
|
8
|
+
#
|
9
|
+
|
10
|
+
# load gem and connect database
|
11
|
+
require 'pampa'
|
12
|
+
|
13
|
+
# parse command line parameters
|
14
|
+
PARSER = BlackStack::SimpleCommandLineParser.new(
|
15
|
+
:description => 'This script starts an infinite loop. Each loop will look for a task to perform. Must be a delay between each loop.',
|
16
|
+
:configuration => [{
|
17
|
+
:name=>'delay',
|
18
|
+
:mandatory=>false,
|
19
|
+
:default=>10,
|
20
|
+
:description=>'Minimum delay between loops. A minimum of 10 seconds is recommended, in order to don\'t hard the database server. Default is 30 seconds.',
|
21
|
+
:type=>BlackStack::SimpleCommandLineParser::INT,
|
22
|
+
}, {
|
23
|
+
:name=>'config',
|
24
|
+
:mandatory=>false,
|
25
|
+
:default=>'config.rb',
|
26
|
+
:description=>'Configuration file. Default: config.',
|
27
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
28
|
+
}, {
|
29
|
+
:name=>'id',
|
30
|
+
:mandatory=>true,
|
31
|
+
:description=>'Write here a unique identifier for the worker.',
|
32
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
33
|
+
}, {
|
34
|
+
:name=>'db',
|
35
|
+
:mandatory=>false,
|
36
|
+
:default=>'postgres',
|
37
|
+
:description=>'Database driver. Values: postgres, crdb. Default: postgres.',
|
38
|
+
:type=>BlackStack::SimpleCommandLineParser::STRING,
|
39
|
+
}, {
|
40
|
+
:name=>'log',
|
41
|
+
:mandatory=>false,
|
42
|
+
:default=>true,
|
43
|
+
:description=>'If write log in the file ./worker.#{id}.log or not. Default: "yes"',
|
44
|
+
:type=>BlackStack::SimpleCommandLineParser::BOOL,
|
45
|
+
}]
|
46
|
+
)
|
47
|
+
|
48
|
+
# create logger
|
49
|
+
l = PARSER.value('log') ? BlackStack::LocalLogger.new("worker.#{PARSER.value('id')}.log") : BlackStack::BaseLogger.new(nil)
|
50
|
+
|
51
|
+
# assign logger to pampa
|
52
|
+
BlackStack::Pampa.set_logger(l)
|
53
|
+
|
54
|
+
# load config file
|
55
|
+
l.logs "Loading #{PARSER.value('config').to_s.blue}... "
|
56
|
+
require PARSER.value('config')
|
57
|
+
l.logf 'done'.green
|
58
|
+
|
59
|
+
l.logs 'Connecting to database... '
|
60
|
+
if PARSER.value('db') == 'postgres'
|
61
|
+
DB = BlackStack::PostgreSQL::connect
|
62
|
+
elsif PARSER.value('db') == 'crdb'
|
63
|
+
DB = BlackStack::CockroachDB::connect
|
64
|
+
else
|
65
|
+
raise 'Unknown database driver.'
|
66
|
+
end
|
67
|
+
l.logf 'done'.green
|
68
|
+
|
69
|
+
begin
|
70
|
+
# getting the worker object
|
71
|
+
l.logs 'Getting worker '+PARSER.value('id').blue+'... '
|
72
|
+
worker = BlackStack::Pampa.workers.select { |w| w.id == PARSER.value('id') }.first
|
73
|
+
raise 'Worker '+PARSER.value('id')+' not found.' if worker.nil?
|
74
|
+
l.logf 'done'.green
|
75
|
+
|
76
|
+
# start the loop
|
77
|
+
while true
|
78
|
+
# get the start loop time
|
79
|
+
l.logs 'Starting loop... '
|
80
|
+
start = Time.now()
|
81
|
+
l.done
|
82
|
+
|
83
|
+
begin
|
84
|
+
l.log ''
|
85
|
+
l.logs 'Starting cycle... '
|
86
|
+
|
87
|
+
BlackStack::Pampa.jobs.each { |job|
|
88
|
+
task = nil
|
89
|
+
begin
|
90
|
+
l.logs 'Processing job '+job.name.blue+'... '
|
91
|
+
tasks = job.occupied_slots(worker)
|
92
|
+
l.logf tasks.size.to_s+' tasks in queue.'
|
93
|
+
|
94
|
+
tasks.each { |t|
|
95
|
+
task = t
|
96
|
+
|
97
|
+
l.logs 'Flag task '+job.name.blue+'.'+task[job.field_primary_key.to_sym].to_s.blue+' started... '
|
98
|
+
job.start(task)
|
99
|
+
l.logf 'done'.green
|
100
|
+
|
101
|
+
l.logs 'Processing task '+task[job.field_primary_key.to_sym].to_s.blue+'... '
|
102
|
+
job.processing_function.call(task, l, job, worker)
|
103
|
+
l.logf 'done'.green
|
104
|
+
|
105
|
+
l.logs 'Flag task '+job.name.blue+'.'+task[job.field_primary_key.to_sym].to_s.blue+' finished... '
|
106
|
+
job.finish(task)
|
107
|
+
l.logf 'done'.green
|
108
|
+
}
|
109
|
+
# note: this catches the CTRL+C signal.
|
110
|
+
# note: this catches the `kill` command, ONLY if it has not the `-9` option.
|
111
|
+
rescue SignalException, SystemExit, Interrupt => e
|
112
|
+
l.logs 'Flag task '+job.name.blue+'.'+task[job.field_primary_key.to_sym].to_s.blue+' interrumpted... '
|
113
|
+
job.finish(task, e)
|
114
|
+
l.logf 'done'.green
|
115
|
+
|
116
|
+
l.logf 'Bye!'.yellow
|
117
|
+
|
118
|
+
raise e
|
119
|
+
|
120
|
+
rescue => e
|
121
|
+
l.logs 'Flag task '+job.name.blue+'.'+task[job.field_primary_key.to_sym].to_s.blue+' failed... '
|
122
|
+
job.finish(task, e)
|
123
|
+
l.logf 'done'.green
|
124
|
+
|
125
|
+
l.logf "Error: #{e.to_console}".red
|
126
|
+
end
|
127
|
+
}
|
128
|
+
|
129
|
+
l.done
|
130
|
+
|
131
|
+
rescue => e
|
132
|
+
l.logf 'Error: '+e.message
|
133
|
+
end
|
134
|
+
|
135
|
+
# release resource
|
136
|
+
l.logs 'Releasing resources... '
|
137
|
+
GC.start
|
138
|
+
DB.disconnect
|
139
|
+
l.logf 'done'.green
|
140
|
+
|
141
|
+
# get the end loop time
|
142
|
+
l.logs 'Ending loop... '
|
143
|
+
finish = Time.now()
|
144
|
+
l.logf 'done'.green
|
145
|
+
|
146
|
+
# get different in seconds between start and finish
|
147
|
+
# if diff > 30 seconds
|
148
|
+
l.logs 'Calculating loop duration... '
|
149
|
+
diff = finish - start
|
150
|
+
l.logf 'done'.green + " (#{diff.to_s.blue})"
|
151
|
+
|
152
|
+
if diff < PARSER.value('delay')
|
153
|
+
# sleep for 30 seconds
|
154
|
+
n = PARSER.value('delay')-diff
|
155
|
+
|
156
|
+
l.logs 'Sleeping for '+n.to_label+' seconds... '
|
157
|
+
sleep n
|
158
|
+
l.logf 'done'.green
|
159
|
+
else
|
160
|
+
l.log 'No sleeping. The loop took '+diff.to_label.blue+' seconds.'
|
161
|
+
end
|
162
|
+
end # while true
|
163
|
+
rescue SignalException, SystemExit, Interrupt
|
164
|
+
# note: this catches the CTRL+C signal.
|
165
|
+
# note: this catches the `kill` command, ONLY if it has not the `-9` option.
|
166
|
+
l.logf 'Process Interrumpted.'.yellow
|
167
|
+
l.log 'Bye!'.yellow
|
168
|
+
rescue => e
|
169
|
+
l.logf "Fatal Error: #{e.to_console}".red
|
170
|
+
rescue
|
171
|
+
l.logf 'Unknown Fatal Error.'.red
|
172
|
+
end
|