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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '095438d108ee4f3cd1cf5d329fb1a0d29c38d6647a130c811e75ed2d73105d81'
4
- data.tar.gz: 45dd332d64c86e75d7e0b0f8e4575e3884a9cf486eabb959371af3b1da2c674c
3
+ metadata.gz: 8610d7df9639c7fe8e09b420795dc61c0cdb76b4df04b04a935689bec1d3d5be
4
+ data.tar.gz: 2c9d0b02219822ca36091805ab2e71ea59285db83255da737acd84d23eda7414
5
5
  SHA512:
6
- metadata.gz: e76a96906f54dafa73f37c4109581f1779c77f086788a98e8278960bf2086228a1fd09851b3e37b94c72920495d009567d1f96699c63b87567925c84b8a1af2c
7
- data.tar.gz: a4869784e7f39a12eb3ef8327584ab773a0a0eac2b22c997cde5dd008e34f13fcdc5e9c0b05b5db86392e3fe8ffa4f8fdd5699052c5e5781d9a9990cae0546d9
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
@@ -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