pampa 2.0.29 → 2.0.30

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 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