pampa_workers 1.1.3
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 +7 -0
- data/lib/basedivision.rb +5 -0
- data/lib/baseworker.rb +5 -0
- data/lib/client.rb +189 -0
- data/lib/division.rb +46 -0
- data/lib/login.rb +7 -0
- data/lib/mybotprocess.rb +348 -0
- data/lib/mychildprocess.rb +9 -0
- data/lib/mycrawlprocess.rb +49 -0
- data/lib/mylocalprocess.rb +170 -0
- data/lib/myparentprocess.rb +142 -0
- data/lib/myprocess.rb +265 -0
- data/lib/myremoteprocess.rb +138 -0
- data/lib/pampa-local.rb +41 -0
- data/lib/pampa_workers.rb +257 -0
- data/lib/params.rb +50 -0
- data/lib/remotedivision.rb +8 -0
- data/lib/remoteworker.rb +8 -0
- data/lib/role.rb +8 -0
- data/lib/timezone.rb +151 -0
- data/lib/user.rb +25 -0
- data/lib/userdivision.rb +5 -0
- data/lib/userrole.rb +8 -0
- data/lib/worker.rb +154 -0
- metadata +169 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
module BlackStack
|
2
|
+
|
3
|
+
# es un proceso sin conexion a base de datos, que itera infinitamente.
|
4
|
+
# en cada iteracion saluda a la central (hello), obtiene parametros (get)
|
5
|
+
class MyChildProcess < BlackStack::MyProcess
|
6
|
+
|
7
|
+
end # MyChildProcess
|
8
|
+
|
9
|
+
end # module BlackStack
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module BlackStack
|
2
|
+
|
3
|
+
# process class
|
4
|
+
class MyCrawlProcess < BlackStack::MyLocalProcess
|
5
|
+
|
6
|
+
attr_accessor :nErrors, :nSuccesses, :browser, :proxy, :bot
|
7
|
+
|
8
|
+
# constructor
|
9
|
+
def initialize(
|
10
|
+
the_worker_name,
|
11
|
+
the_division_name,
|
12
|
+
the_minimum_enlapsed_seconds=MyProcess::DEFAULT_MINIMUM_ENLAPSED_SECONDS,
|
13
|
+
the_verify_configuration=true,
|
14
|
+
the_email=nil,
|
15
|
+
the_password=nil
|
16
|
+
)
|
17
|
+
super(the_worker_name, the_division_name, the_minimum_enlapsed_seconds, the_verify_configuration, the_email, the_password)
|
18
|
+
self.nErrors = 0
|
19
|
+
self.nSuccesses = 0
|
20
|
+
self.browser = nil
|
21
|
+
self.proxy = nil
|
22
|
+
self.bot = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def canRun?()
|
26
|
+
super &&
|
27
|
+
nErrors < Params.getValue("crawl.company.discretion.max_errors") &&
|
28
|
+
nSuccesses < Params.getValue("crawl.company.discretion.max_successes")
|
29
|
+
#(Params.getValue("crawl.company.use_proxy")==false || Company.availableProxiesWithDiscretionForCrawl() > 0)
|
30
|
+
end
|
31
|
+
|
32
|
+
def whyCantRun()
|
33
|
+
ret = super
|
34
|
+
if (ret.to_s.size == 0)
|
35
|
+
if (self.nErrors >= Params.getValue("crawl.company.discretion.max_errors"))
|
36
|
+
return "Reached the max number of errors (#{self.nErrors.to_s})"
|
37
|
+
end
|
38
|
+
|
39
|
+
if (self.nSuccesses >= Params.getValue("crawl.company.discretion.max_successes"))
|
40
|
+
return "Reached the max number of successes (#{self.nSuccesses.to_s})"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
return ret
|
44
|
+
end
|
45
|
+
|
46
|
+
end # class MyCrawlProcess
|
47
|
+
|
48
|
+
|
49
|
+
end # module BlackStack
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module BlackStack
|
2
|
+
|
3
|
+
# Process located in the same LAN than the Database Server
|
4
|
+
class MyLocalProcess < BlackStack::MyChildProcess
|
5
|
+
|
6
|
+
# constructor
|
7
|
+
def initialize(
|
8
|
+
the_worker_name,
|
9
|
+
the_division_name,
|
10
|
+
the_minimum_enlapsed_seconds=BlackStack::MyProcess::DEFAULT_MINIMUM_ENLAPSED_SECONDS,
|
11
|
+
the_verify_configuration=true,
|
12
|
+
the_email=nil,
|
13
|
+
the_password=nil
|
14
|
+
)
|
15
|
+
super(the_worker_name, the_division_name, the_minimum_enlapsed_seconds, the_verify_configuration, the_email, the_password)
|
16
|
+
end
|
17
|
+
|
18
|
+
def division()
|
19
|
+
if (self.division_name != "local")
|
20
|
+
d = BlackStack::Division.where(:name=>self.division_name).first
|
21
|
+
if (d!=nil)
|
22
|
+
return BlackStack::Division.where(:db_name=>d.db_name, :home=>true).first
|
23
|
+
else
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
else
|
27
|
+
return BlackStack::Division.where(:central=>true).first
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def worker()
|
32
|
+
BlackStack::Worker.where(:name=>self.fullWorkerName).first
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# update worker configuration in the division
|
37
|
+
def updateWorker()
|
38
|
+
w = BlackStack::Worker.where(:name=>self.fullWorkerName).first
|
39
|
+
if (w==nil)
|
40
|
+
w = BlackStack::Worker.new
|
41
|
+
w.id = guid()
|
42
|
+
w.process = ''
|
43
|
+
w.last_ping_time = now()
|
44
|
+
w.name = self.fullWorkerName
|
45
|
+
w.assigned_process = self.assigned_process
|
46
|
+
w.id_client = self.id_client
|
47
|
+
w.division_name = self.division_name
|
48
|
+
w.save
|
49
|
+
end
|
50
|
+
if (w!=nil)
|
51
|
+
w.assigned_process = self.assigned_process
|
52
|
+
w.id_client = self.id_client
|
53
|
+
w.division_name = self.division_name
|
54
|
+
w.id_division = self.id_division
|
55
|
+
w.save
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def run()
|
60
|
+
super
|
61
|
+
|
62
|
+
# creo el objeto logger
|
63
|
+
self.logger = RemoteLogger.new(
|
64
|
+
"#{self.fullWorkerName}.log",
|
65
|
+
BlackStack::Pampa::api_protocol,
|
66
|
+
BlackStack::Pampa::api_domain,
|
67
|
+
BlackStack::Pampa::api_port,
|
68
|
+
BlackStack::Pampa::api_key,
|
69
|
+
self.id_client # ID of the client that has this thread assigned
|
70
|
+
)
|
71
|
+
|
72
|
+
# announcing my in the log
|
73
|
+
logger.log "Child process is alive!"
|
74
|
+
|
75
|
+
# obtengo los parametros del worker
|
76
|
+
logger.logs "Update from central (1-local)... "
|
77
|
+
self.get
|
78
|
+
logger.done
|
79
|
+
|
80
|
+
# actualizo los datos de este worker (parent process)
|
81
|
+
logger.logs "Update worker (1-local)... "
|
82
|
+
self.updateWorker
|
83
|
+
logger.done
|
84
|
+
|
85
|
+
# actualizo los datos de este worker (parent process)
|
86
|
+
logger.logs "Switch logger id_client (log folder may change)... "
|
87
|
+
self.logger.id_client = self.id_client
|
88
|
+
logger.done
|
89
|
+
|
90
|
+
while (self.canRun?)
|
91
|
+
# reseteo en contador nested del logger
|
92
|
+
self.logger.reset()
|
93
|
+
|
94
|
+
# announcing my in the log
|
95
|
+
logger.log "Going to Run Local"
|
96
|
+
logger.log "Process: #{self.assigned_process.to_s}."
|
97
|
+
logger.log "Client: #{(self.id_client.to_s.size==0)? 'n/a' : self.id_client.to_s}."
|
98
|
+
|
99
|
+
# obtengo la hora de inicio
|
100
|
+
start_time = Time.now
|
101
|
+
|
102
|
+
begin
|
103
|
+
# libero recursos
|
104
|
+
logger.logs "Release resources... "
|
105
|
+
GC.start
|
106
|
+
DB.disconnect
|
107
|
+
logger.done
|
108
|
+
|
109
|
+
# cargo el objeto worker
|
110
|
+
logger.logs "Load the worker... "
|
111
|
+
the_worker = self.worker
|
112
|
+
logger.done
|
113
|
+
|
114
|
+
# actualizo el valor del proceso que corre actualmente para este worker
|
115
|
+
logger.logs "Update current process... "
|
116
|
+
the_worker.process=self.assigned_process
|
117
|
+
the_worker.active = true
|
118
|
+
the_worker.save()
|
119
|
+
logger.done
|
120
|
+
|
121
|
+
logger.logs "Ping... "
|
122
|
+
the_worker.ping()
|
123
|
+
logger.done
|
124
|
+
|
125
|
+
# corro el procesamiento
|
126
|
+
self.process(ARGV)
|
127
|
+
|
128
|
+
rescue => e
|
129
|
+
puts ""
|
130
|
+
logger.log "Local Process Error: " + e.to_s + "\r\n" + e.backtrace.join("\r\n").to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
# obtengo los parametros del worker
|
134
|
+
logger.logs "Update from central (2)... "
|
135
|
+
self.get
|
136
|
+
logger.done
|
137
|
+
|
138
|
+
# actualizo los datos de este worker (parent process)
|
139
|
+
logger.logs "Update worker (2)... "
|
140
|
+
self.updateWorker
|
141
|
+
logger.done
|
142
|
+
|
143
|
+
# sleep
|
144
|
+
logger.logs "Sleep... "
|
145
|
+
self.doSleep(start_time)
|
146
|
+
logger.done
|
147
|
+
|
148
|
+
logger.log "-------------------------------------------"
|
149
|
+
|
150
|
+
DB.disconnect
|
151
|
+
GC.start
|
152
|
+
end # main while
|
153
|
+
|
154
|
+
#
|
155
|
+
logger.log "Process Finish!"
|
156
|
+
logger.log "Finish Reason: " + self.whyCantRun.to_s
|
157
|
+
|
158
|
+
#
|
159
|
+
logger.logs "Disconnect to Database... "
|
160
|
+
begin
|
161
|
+
DB.disconnect()
|
162
|
+
logger.done
|
163
|
+
rescue => e
|
164
|
+
logger.error(e)
|
165
|
+
end
|
166
|
+
end # run
|
167
|
+
|
168
|
+
end # class MyLocalProcess
|
169
|
+
|
170
|
+
end # module BlackStack
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module BlackStack
|
2
|
+
|
3
|
+
# es un proceso sin conexion a base de datos, que itera infinitamente.
|
4
|
+
# en cada iteracion saluda a la central (hello), obtiene parametros (get)
|
5
|
+
class MyParentProcess < BlackStack::MyProcess
|
6
|
+
def run()
|
7
|
+
super
|
8
|
+
|
9
|
+
# creo el objeto logger
|
10
|
+
self.logger = BlackStack::RemoteLogger.new(
|
11
|
+
"#{self.fullWorkerName}.log",
|
12
|
+
BlackStack::Pampa::api_protocol,
|
13
|
+
BlackStack::Pampa::api_domain,
|
14
|
+
BlackStack::Pampa::api_port,
|
15
|
+
BlackStack::Pampa::api_key,
|
16
|
+
self.id_client # ID of the client that has this thread assigned
|
17
|
+
)
|
18
|
+
|
19
|
+
#
|
20
|
+
pid = nil
|
21
|
+
while (true)
|
22
|
+
begin
|
23
|
+
GC.start # 331 - avoid lack of memory
|
24
|
+
#DB.disconnect # este proceso esta desacoplado de la conexion a la base de datos
|
25
|
+
|
26
|
+
# reseteo en contador nested del logger
|
27
|
+
self.logger.reset()
|
28
|
+
|
29
|
+
# get the start time
|
30
|
+
start_time = Time.now
|
31
|
+
|
32
|
+
# consulto a la central por la division asignada
|
33
|
+
url = "#{BlackStack::Pampa::api_url}/api1.3/pampa/hello.json"
|
34
|
+
logger.logs("Hello to the central... ")
|
35
|
+
res = BlackStack::Netting::call_post(url, {
|
36
|
+
'api_key' => BlackStack::Pampa::api_key,
|
37
|
+
'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
|
38
|
+
)
|
39
|
+
parsed = JSON.parse(res.body)
|
40
|
+
if (parsed['status'] != BlackStack::Netting::SUCCESS)
|
41
|
+
self.logger.logf("Error: " + parsed['status'].to_s)
|
42
|
+
else
|
43
|
+
self.logger.done
|
44
|
+
|
45
|
+
logger.logs("Get worker data... ")
|
46
|
+
url = "#{BlackStack::Pampa::api_url}/api1.3/pampa/get.json"
|
47
|
+
res = BlackStack::Netting::call_post(url, {
|
48
|
+
'api_key' => BlackStack::Pampa::api_key,
|
49
|
+
'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
|
50
|
+
)
|
51
|
+
parsed = JSON.parse(res.body)
|
52
|
+
if (parsed['status'] != BlackStack::Netting::SUCCESS)
|
53
|
+
self.logger.logf("Error: " + parsed['status'].to_s)
|
54
|
+
else
|
55
|
+
# map response
|
56
|
+
self.id = parsed['id']
|
57
|
+
self.assigned_process = parsed['assigned_process']
|
58
|
+
self.id_client = parsed['id_client']
|
59
|
+
self.id_division = parsed['id_division']
|
60
|
+
self.division_name = parsed['division_name']
|
61
|
+
self.ws_url = parsed['ws_url']
|
62
|
+
self.ws_port = parsed['ws_port']
|
63
|
+
self.logger.logf "done (#{self.division_name})"
|
64
|
+
|
65
|
+
#
|
66
|
+
self.logger.logs "Notify division... "
|
67
|
+
if self.division_name.to_s.size == 0
|
68
|
+
self.logger.logf "no division assigned"
|
69
|
+
else
|
70
|
+
self.notify # notifico a la division
|
71
|
+
self.logger.done
|
72
|
+
|
73
|
+
#
|
74
|
+
self.logger.logs "Spawn child process... "
|
75
|
+
# lanzo el proceso
|
76
|
+
if self.assigned_process.to_s.size > 0
|
77
|
+
command = "ruby #{self.assigned_process} name=#{self.worker_name} division=#{self.division_name}"
|
78
|
+
pid = Process.spawn(command)
|
79
|
+
logger.logf "done (pid=#{pid.to_s})"
|
80
|
+
|
81
|
+
logger.log("Wait to child process to finish.")
|
82
|
+
Process.wait(pid)
|
83
|
+
else
|
84
|
+
if self.assigned_process.to_s.size == 0
|
85
|
+
self.logger.logf "no process assigned"
|
86
|
+
end
|
87
|
+
end # if self.assigned_process.to_s.size > 0
|
88
|
+
end # if self.division_name.to_s.size == 0
|
89
|
+
end # if (parsed['status'] != "success") <-- #{BlackStack::Pampa::api_url}/api1.3/pampa/get.json
|
90
|
+
end # if (parsed['status'] != "success") <-- #{BlackStack::Pampa::api_url}/api1.3/pampa/hello.json
|
91
|
+
|
92
|
+
#
|
93
|
+
logger.logs "Sleep... "
|
94
|
+
self.doSleep(start_time)
|
95
|
+
logger.done
|
96
|
+
|
97
|
+
logger.log "-------------------------------------------"
|
98
|
+
|
99
|
+
rescue Interrupt => e
|
100
|
+
logger.reset
|
101
|
+
|
102
|
+
logger.log "Interrupt signal!"
|
103
|
+
|
104
|
+
logger.logs "Kill process... "
|
105
|
+
if (pid!=nil)
|
106
|
+
system("taskkill /im #{pid.to_s} /f /t >nul 2>&1")
|
107
|
+
end
|
108
|
+
logger.done
|
109
|
+
|
110
|
+
logger.logs "Disconnect to Database... "
|
111
|
+
begin
|
112
|
+
# DB.disconnect()
|
113
|
+
logger.done
|
114
|
+
rescue => e
|
115
|
+
logger.error(e)
|
116
|
+
end
|
117
|
+
|
118
|
+
logger.log "Process is out."
|
119
|
+
exit(0)
|
120
|
+
|
121
|
+
rescue => e
|
122
|
+
begin
|
123
|
+
logger.log "Unhandled exception: #{e.to_s}\r\n#{e.backtrace.join("\r\n").to_s}"
|
124
|
+
logger.logs "Sleep #{self.minimum_enlapsed_seconds.to_s} seconds... "
|
125
|
+
sleep(self.minimum_enlapsed_seconds)
|
126
|
+
logger.done
|
127
|
+
rescue => e
|
128
|
+
puts "Fatal error: #{e.to_s}"
|
129
|
+
print "Sleep #{self.minimum_enlapsed_seconds.to_s} seconds... "
|
130
|
+
sleep(self.minimum_enlapsed_seconds)
|
131
|
+
puts
|
132
|
+
end
|
133
|
+
|
134
|
+
end # rescue
|
135
|
+
|
136
|
+
end # while
|
137
|
+
|
138
|
+
end # def run()
|
139
|
+
|
140
|
+
end # class MyParentProcess
|
141
|
+
|
142
|
+
end # module BlackStack
|
data/lib/myprocess.rb
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
module BlackStack
|
2
|
+
|
3
|
+
class MyProcess
|
4
|
+
DEFAULT_MINIMUM_ENLAPSED_SECONDS = 60
|
5
|
+
|
6
|
+
attr_accessor :assigned_process_changed, :assigned_division_changed, :verify_configuration
|
7
|
+
attr_accessor :logger, :id, :worker_name, :division_name, :minimum_enlapsed_seconds, :assigned_process, :id_client, :id_division, :ws_url, :ws_port
|
8
|
+
attr_accessor :email, :password
|
9
|
+
|
10
|
+
# constructor
|
11
|
+
def initialize(
|
12
|
+
the_worker_name,
|
13
|
+
the_division_name,
|
14
|
+
the_minimum_enlapsed_seconds=MyProcess::DEFAULT_MINIMUM_ENLAPSED_SECONDS,
|
15
|
+
the_verify_configuration=true,
|
16
|
+
the_email=nil,
|
17
|
+
the_password=nil
|
18
|
+
)
|
19
|
+
self.assigned_process_changed = false
|
20
|
+
self.assigned_division_changed = false
|
21
|
+
self.assigned_process = File.expand_path($0)
|
22
|
+
self.worker_name = "#{the_worker_name}"
|
23
|
+
self.division_name = the_division_name
|
24
|
+
self.minimum_enlapsed_seconds = the_minimum_enlapsed_seconds
|
25
|
+
self.verify_configuration = the_verify_configuration
|
26
|
+
self.email = the_email
|
27
|
+
self.password = the_password
|
28
|
+
end
|
29
|
+
|
30
|
+
# retrieves the id of the current process
|
31
|
+
def pid()
|
32
|
+
Process.pid.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
# Retorna un array de hashes.
|
36
|
+
# => Cada elemento del hash tiene la forma: {:executablepath, :pid, :ppid},
|
37
|
+
# => donde imagename es el patch completo del proceso, pid es el id del proceso
|
38
|
+
# => y ppid es el id del proceso padre.
|
39
|
+
def list()
|
40
|
+
a = []
|
41
|
+
s = `wmic process get executablepath,processid,parentprocessid`
|
42
|
+
s.split(/\n+/).each { |e|
|
43
|
+
aux = e.strip.scan(/^(.+)\s+(\d+)\s+(\d+)$/)[0]
|
44
|
+
if (aux!=nil)
|
45
|
+
if (aux.size>=3)
|
46
|
+
a << {
|
47
|
+
:executablepath => aux[0].strip.to_s,
|
48
|
+
:pid => aux[2].to_s, # TODO: deberia ser aux[1], pero por algo que no entiendo ahora el pid viene en aux[2]
|
49
|
+
:ppid => aux[1].to_s, # TODO: deberia ser aux[2], pero por algo que no entiendo ahora el pid viene en aux[1]
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
}
|
54
|
+
a
|
55
|
+
end
|
56
|
+
|
57
|
+
# ejecuta TASKKILL /F /PID #{the_pid} y retorna el output del comando
|
58
|
+
def self.kill(the_pid)
|
59
|
+
system("TASKKILL /F /PID #{the_pid}")
|
60
|
+
end
|
61
|
+
|
62
|
+
# obtiene la diferencia en segundos entre la hora actual y el parametro the_start_time.
|
63
|
+
# si la diferencia es mayor al atributo minimum_enlapsed_seconds, entonces duerme el tiempo restante.
|
64
|
+
def doSleep(the_start_time)
|
65
|
+
# si el proceso tardo menos del minimum_enlapsed_seconds, entonces duermo el tiempo restante
|
66
|
+
end_time = Time.now
|
67
|
+
elapsed_seconds = end_time - the_start_time # in seconds
|
68
|
+
if (elapsed_seconds < self.minimum_enlapsed_seconds)
|
69
|
+
sleep_seconds = self.minimum_enlapsed_seconds - elapsed_seconds
|
70
|
+
sleep(sleep_seconds)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# This function works in windows only
|
75
|
+
# TODO: Esta funcion no retorna la mac address completa
|
76
|
+
# TODO: Validar que no se retorne una macaddress virtual, con todos valores en 0
|
77
|
+
def self.macaddress()
|
78
|
+
BlackStack::SimpleHostMonitoring.macaddress
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.fullWorkerName(name)
|
82
|
+
"#{Socket.gethostname}.#{MyProcess.macaddress}.#{name}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def fullWorkerName()
|
86
|
+
MyProcess.fullWorkerName(self.worker_name)
|
87
|
+
end
|
88
|
+
|
89
|
+
# saluda a la central
|
90
|
+
def hello()
|
91
|
+
# me notifico a la central. obtengo asignacion si ya la tenia
|
92
|
+
url = "#{BlackStack::Pampa::api_url}/api1.3/pampa/hello.json"
|
93
|
+
res = BlackStack::Netting::call_post(url, {
|
94
|
+
'api_key' => BlackStack::Pampa::api_key,
|
95
|
+
'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
|
96
|
+
)
|
97
|
+
parsed = JSON.parse(res.body)
|
98
|
+
if (parsed['status'] != BlackStack::Netting::SUCCESS)
|
99
|
+
raise parsed['status'].to_s
|
100
|
+
end
|
101
|
+
end # hello()
|
102
|
+
|
103
|
+
# notifico mis parametros (assigned_process, id_client) a la division asignada
|
104
|
+
def set(new_assigned_process, new_id_client)
|
105
|
+
if (self.ws_url.to_s.size > 0 && self.ws_port.to_s.size > 0)
|
106
|
+
url = "#{BlackStack::Pampa::api_protocol}://#{self.ws_url.to_s}:#{self.ws_port.to_s}/api1.3/pampa/notify.json"
|
107
|
+
res = BlackStack::Netting::call_post(url, {
|
108
|
+
'api_key' => BlackStack::Pampa::api_key,
|
109
|
+
'name' => self.fullWorkerName,
|
110
|
+
'assigned_process' => new_assigned_process,
|
111
|
+
'id_client' => new_id_client }.merge( BlackStack::RemoteHost.new.poll )
|
112
|
+
)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# obtiene sus parametros de la central
|
117
|
+
def get()
|
118
|
+
# me notifico a la central. obtengo asignacion que tenga
|
119
|
+
url = "#{BlackStack::Pampa::api_url}/api1.3/pampa/get.json"
|
120
|
+
res = BlackStack::Netting::call_post(url, {
|
121
|
+
'api_key' => BlackStack::Pampa::api_key,
|
122
|
+
'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
|
123
|
+
)
|
124
|
+
parsed = JSON.parse(res.body)
|
125
|
+
if (parsed['status'] != BlackStack::Netting::SUCCESS)
|
126
|
+
raise parsed['status'].to_s
|
127
|
+
else
|
128
|
+
if self.verify_configuration
|
129
|
+
# si ya tenia un proceso asignado, y ahora se le asigna un nuevo proceso
|
130
|
+
if self.assigned_process.to_s.size > 0
|
131
|
+
a = File.expand_path(self.assigned_process)
|
132
|
+
b = File.expand_path(parsed['assigned_process'])
|
133
|
+
if a != b
|
134
|
+
self.assigned_process_changed = true
|
135
|
+
else
|
136
|
+
self.assigned_process_changed = false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# si ya tenia un proceso asignado, y ahora se le asigna un nuevo proceso
|
141
|
+
if self.id_division.to_s.size > 0
|
142
|
+
if self.id_division.to_guid != parsed['id_division'].to_guid
|
143
|
+
self.assigned_division_changed = true
|
144
|
+
else
|
145
|
+
self.assigned_division_changed = false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end # verify_configuration
|
149
|
+
|
150
|
+
# si ya tenia asignada una division, entonces le notifico mi nueva configuracion
|
151
|
+
self.set(parsed['assigned_process'], parsed['id_client'])
|
152
|
+
|
153
|
+
self.id = parsed['id']
|
154
|
+
self.assigned_process = parsed['assigned_process']
|
155
|
+
self.id_client = parsed['id_client']
|
156
|
+
self.id_division = parsed['id_division']
|
157
|
+
self.division_name = parsed['division_name']
|
158
|
+
self.ws_url = parsed['ws_url']
|
159
|
+
self.ws_port = parsed['ws_port']
|
160
|
+
|
161
|
+
# le notifico a la nueva division asignada mi nueva configuracion
|
162
|
+
self.set(parsed['assigned_process'], parsed['id_client'])
|
163
|
+
end
|
164
|
+
end # get()
|
165
|
+
|
166
|
+
|
167
|
+
# update worker configuration in the division
|
168
|
+
def updateWorker()
|
169
|
+
raise "Abstract Method."
|
170
|
+
end
|
171
|
+
|
172
|
+
# ping the central database
|
173
|
+
def ping()
|
174
|
+
# me notifico a la central.
|
175
|
+
url = "#{BlackStack::Pampa::api_url}/api1.3/pampa/ping.json"
|
176
|
+
res = BlackStack::Netting::call_post(url, {
|
177
|
+
'api_key' => BlackStack::Pampa::api_key,
|
178
|
+
'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
|
179
|
+
)
|
180
|
+
parsed = JSON.parse(res.body)
|
181
|
+
if (parsed['status'] != BlackStack::Netting::SUCCESS)
|
182
|
+
raise parsed['status'].to_s
|
183
|
+
end
|
184
|
+
|
185
|
+
# me notifico a la division.
|
186
|
+
if (self.ws_url != nil && self.ws_port != nil)
|
187
|
+
url = "#{BlackStack::Pampa::api_protocol}://#{self.ws_url.to_s}:#{self.ws_port.to_s}/api1.3/pampa/ping.json"
|
188
|
+
res = BlackStack::Netting::call_post(url, {
|
189
|
+
'api_key' => BlackStack::Pampa::api_key,
|
190
|
+
'name' => self.fullWorkerName }.merge( BlackStack::RemoteHost.new.poll )
|
191
|
+
)
|
192
|
+
parsed = JSON.parse(res.body)
|
193
|
+
if (parsed['status'] != "success")
|
194
|
+
raise parsed['status'].to_s
|
195
|
+
end
|
196
|
+
end # if
|
197
|
+
end # ping()
|
198
|
+
|
199
|
+
# se notifica al dispatcher de la division
|
200
|
+
def notify()
|
201
|
+
if (self.ws_url==nil || self.ws_port==nil)
|
202
|
+
raise "Cannot notify. Worker has not parameters."
|
203
|
+
end
|
204
|
+
|
205
|
+
# me notifico a la division. obtengo trabajo
|
206
|
+
url = "#{BlackStack::Pampa::api_protocol}://#{self.ws_url}:#{self.ws_port}/api1.3/pampa/notify.json"
|
207
|
+
res = BlackStack::Netting::call_post(url,
|
208
|
+
{
|
209
|
+
'api_key' => BlackStack::Pampa::api_key,
|
210
|
+
'name' => self.fullWorkerName,
|
211
|
+
'assigned_process' => self.assigned_process,
|
212
|
+
'id_client' => self.id_client,
|
213
|
+
'id_division' => self.id_division }.merge( BlackStack::RemoteHost.new.poll )
|
214
|
+
)
|
215
|
+
parsed = JSON.parse(res.body)
|
216
|
+
if (parsed['status'] != "success")
|
217
|
+
raise parsed['status'].to_s
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Get the data object of the divison assigned to this worker.
|
222
|
+
# Needs database connections. So it's available for ChildProcess only.
|
223
|
+
def division()
|
224
|
+
raise "This is an abstract method."
|
225
|
+
end
|
226
|
+
|
227
|
+
# Get the data object of worker linked to this process.
|
228
|
+
# Needs database connections. So it's available for ChildProcess only.
|
229
|
+
def worker()
|
230
|
+
raise "This is an abstract method."
|
231
|
+
end
|
232
|
+
|
233
|
+
# retorna true si el proceso hijo (child) esta habilitado para trabajar.
|
234
|
+
def canRun?()
|
235
|
+
self.assigned_process_changed == false &&
|
236
|
+
self.assigned_division_changed == false
|
237
|
+
end
|
238
|
+
|
239
|
+
def whyCantRun()
|
240
|
+
if self.assigned_process_changed == true
|
241
|
+
return "Assigned process has changed."
|
242
|
+
elsif self.assigned_division_changed == true
|
243
|
+
return "Assigned division has changed."
|
244
|
+
else
|
245
|
+
return "unknown"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# este metodo
|
250
|
+
# ejecuta el trabajo para el que fue creado el objeto.
|
251
|
+
def process(argv)
|
252
|
+
raise "This is an abstract method."
|
253
|
+
end
|
254
|
+
|
255
|
+
# ejecuta el proceso, en modo parent, bot o child segun la clase que se implemente.
|
256
|
+
# en modo parent, hace un loop infinito.
|
257
|
+
# en modo bot o child, hace un loop hasta que el metodo canRun? retorne false.
|
258
|
+
# en modo bot o child, invoca al metodo process() en cada ciclo.
|
259
|
+
def run()
|
260
|
+
#raise "This is an abstract method"
|
261
|
+
end # run
|
262
|
+
|
263
|
+
end # class MyProcess
|
264
|
+
|
265
|
+
end # module BlackStack
|