pampa_workers 0.0.39

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.
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+
3
+ class RemoteDivision
4
+ attr_accessor :name
5
+ include BlackStack::BaseDivision
6
+ end # RemoteDivision
7
+
8
+ end # module BlackStack
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+
3
+ class RemoteWorker
4
+ attr_accessor :id, :process, :last_ping_time, :name, :active, :id_division, :assigned_process, :id_object, :division_name, :ws_url, :ws_port, :division
5
+ include BlackStack::BaseWorker
6
+ end # Remote Worker
7
+
8
+ end # module BlackStack
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+ class Role < Sequel::Model(:role)
3
+ BlackStack::Role.dataset = BlackStack::Role.dataset.disable_insert_output
4
+
5
+ ROLE_PRISMA_USER = "prisma.user"
6
+
7
+ end
8
+ end # module BlackStack
@@ -0,0 +1,151 @@
1
+ module BlackStack
2
+ class Timezone < Sequel::Model(:timezone)
3
+ BlackStack::Timezone.dataset = BlackStack::Timezone.dataset.disable_insert_output
4
+
5
+ # Recibe un string con formato "+HH:MM".
6
+ # Retorna la cantidad de horas como un numero real, con decimales.
7
+ def self.descToFloat(s)
8
+ sign = s[0]
9
+ if (sign=="+")
10
+ n = 1.0
11
+ else
12
+ n = -1.0
13
+ end
14
+ hours = s[1..2]
15
+ minutes = s[4..5]
16
+ int_part = hours.to_f
17
+ dec_part = minutes.to_f / 60.00
18
+ ret = n*(int_part + dec_part)
19
+ return ret.to_f
20
+ end
21
+
22
+ # Recibe la cantidad de horas como un numero real, con decimales.
23
+ # Retorna un string con formato "+HH:MM".
24
+ def self.floatToDesc(x)
25
+ int_part = x.to_i
26
+ dec_part = (x-int_part.to_f).round(2).abs
27
+ hours = int_part
28
+ minutes = (dec_part * 60.00).to_i
29
+ if (hours<0)
30
+ desc = "%03d" % hours
31
+ else
32
+ desc = "+" + "%02d" % hours
33
+ end
34
+ desc += ":" + "%02d" % minutes
35
+ return desc
36
+ end
37
+
38
+ # Example: '-03:00'
39
+ # Example: ' 08:00'
40
+ def self.getDatabaseOffset()
41
+ dbtime = DB["select SYSDATETIMEOFFSET() AS o"].first[:o].to_s
42
+ #puts ""
43
+ #puts ""
44
+ #puts "dbtime:#{dbtime.to_s}:."
45
+ #puts ""
46
+ #puts ""
47
+ ret = "#{dbtime[-5..-3]}:#{dbtime[-2..-1]}"
48
+ ret[0] = '+' if ret[0]!='-'
49
+ #puts ""
50
+ #puts ""
51
+ #puts "dbtime:#{ret.to_s}:."
52
+ #puts ""
53
+ #puts ""
54
+ return ret
55
+ end
56
+
57
+ # Convierte el atributo offset en un string con formato de hora.
58
+ # Ejemplos: 5.0 => 05:00, 5.5 => 05:30, -5.75 => -05:45
59
+ def offsetDescription()
60
+ return BlackStack::Timezone.floatToDesc(self.offset.to_f)
61
+ end
62
+
63
+ # Convierte una hora almacenada en el servidor de bases de datos, a la hora en esta zona horaria.
64
+ # Recibe un string con formato "+HH:MM".
65
+ # Retorna un string con formato "+HH:MM".
66
+ def convertFromThisTimeZoneToDatabaseTime(s_time_in_client_timezone)
67
+ f_time_in_client_timezone = BlackStack::Timezone.descToFloat(s_time_in_client_timezone)
68
+ s = BlackStack::Timezone.getDatabaseOffset()
69
+ x = BlackStack::Timezone.descToFloat(s) # database offset
70
+ y = self.offset # client offset
71
+ z = y - x
72
+ return BlackStack::Timezone.floatToDesc((f_time_in_client_timezone.to_f + z.to_f).modulo(24))
73
+ end
74
+
75
+ # Convierte una hora almacenada en el servidor de bases de datos, a la hora en esta zona horaria.
76
+ # Recibe un string con formato "+HH:MM".
77
+ # Retorna un string con formato "+HH:MM".
78
+ def convertFromDatabaseTimeToThisTimeZone(s_time_in_database)
79
+ f_time_in_database = BlackStack::Timezone.descToFloat(s_time_in_database)
80
+ s = BlackStack::Timezone.getDatabaseOffset()
81
+ x = BlackStack::Timezone.descToFloat(s) # database offset
82
+ y = self.offset # client offset
83
+ z = y - x
84
+ return BlackStack::Timezone.floatToDesc((f_time_in_database.to_f - z.to_f).modulo(24))
85
+ end
86
+
87
+ # Convierte una fecha-hora almacenada en el servidor de bases de datos, a la hora en esta zona horaria.
88
+ # Recibe un string con formato "YYYY-MM-DD HH:MM:SS".
89
+ # Retorna un string con formato "YYYY-MM-DD HH:MM:SS".
90
+ def convertFromDatabaseDateTimeToThisTimeZone(s_datetime_in_database)
91
+ s = BlackStack::Timezone.getDatabaseOffset() # Example: '-03:00'
92
+ #puts ""
93
+ #puts ""
94
+ #puts "s:#{s.to_s}:."
95
+ #puts ""
96
+ #puts ""
97
+ x = BlackStack::Timezone.descToFloat(s) # database offset. Number of hours, with decimals
98
+ #puts ""
99
+ #puts ""
100
+ #puts "x:#{x.to_s}:."
101
+ #puts ""
102
+ #puts ""
103
+ y = self.offset # client offset
104
+ #puts ""
105
+ #puts ""
106
+ #puts "y:#{y.to_s}:."
107
+ #puts ""
108
+ #puts ""
109
+ z = y - x
110
+ #puts ""
111
+ #puts ""
112
+ #puts "z:#{z.to_s}:."
113
+ #puts ""
114
+ #puts ""
115
+ ret = DB["SELECT DATEADD(HH, #{z.to_s}, '#{s_datetime_in_database}') AS o"].first[:o].to_s[0..18]
116
+ #puts ""
117
+ #puts ""
118
+ #puts "convertFromDatabaseDateTimeToThisTimeZone:#{ret}:."
119
+ #puts ""
120
+ #puts ""
121
+
122
+ return ret
123
+ end
124
+
125
+ #
126
+ def get_now()
127
+ datetime1 = DB["SELECT GETDATE() AS o"].first[:o].to_s[0..18]
128
+ datetime2 = self.convertFromDatabaseDateTimeToThisTimeZone(datetime1)
129
+ #puts ""
130
+ #puts ""
131
+ #puts "timezone:#{self.large_description}:."
132
+ #puts "datetime1:#{datetime1}:."
133
+ #puts "datetime2:#{datetime2}:."
134
+ #puts ""
135
+ #puts ""
136
+ yy = datetime2[0..3] # yyyy-mm-dd hh:mi:ss
137
+ mm = datetime2[5..6]
138
+ dd = datetime2[8..9]
139
+ hh = datetime2[11..12]
140
+ mi = datetime2[14..15]
141
+ ss = datetime2[17..18]
142
+ #puts ""
143
+ #puts ""
144
+ #puts "get_now:#{yy}-#{mm}-#{dd} #{hh}:#{mi}:#{ss}:."
145
+ #puts ""
146
+ #puts ""
147
+ return Time.new(yy,mm,dd,hh,mi,ss)
148
+ end
149
+
150
+ end
151
+ end # module BlackStack
@@ -0,0 +1,25 @@
1
+ module BlackStack
2
+ class User < Sequel::Model(:user)
3
+ BlackStack::User.dataset = BlackStack::User.dataset.disable_insert_output
4
+ many_to_one :client, :class=>:'BlackStack::Client', :key=>:id_client
5
+ one_to_many :user_roles, :class=>:'BlackStack::UserRole', :key=>:id_user
6
+
7
+ # TODO: agregar todos los arrays de un usuario
8
+ # => one_to_many :searches, :class=>:Search, :key=>:id_user
9
+ # => one_to_many :emlist, :class=>:EmList, :key=>:id_user
10
+ # => one_to_many :emlist, :class=>:EmList, :key=>:id_user
11
+ # => etc.
12
+
13
+ # retorna la primera division habilitada a la que pertenezca este usuario
14
+ def division
15
+ row = DB[
16
+ "SELECT d.id " +
17
+ "FROM division d WITH (NOLOCK) " +
18
+ "JOIN user_division ud WITH (NOLOCK) ON (d.id=ud.id_division AND ud.id_user='#{self.id}') " +
19
+ "WHERE ISNULL(d.available,0) = 1 "
20
+ ].first
21
+ return nil if row.nil?
22
+ return BlackStack::Division.where(:id=>row[:id]).first if !row.nil?
23
+ end
24
+ end # class User
25
+ end # module BlackStack
@@ -0,0 +1,5 @@
1
+ module BlackStack
2
+ class UserDivision < Sequel::Model(:user_division)
3
+ BlackStack::UserDivision.dataset = BlackStack::UserDivision.dataset.disable_insert_output
4
+ end
5
+ end # module BlackStack
@@ -0,0 +1,8 @@
1
+ module BlackStack
2
+ class UserRole < Sequel::Model(:user_role)
3
+ BlackStack::UserRole.dataset = BlackStack::UserRole.dataset.disable_insert_output
4
+ many_to_one :user, :class=>:'BlackStack::User', :key=>:id_user
5
+ many_to_one :role, :class=>:'BlackStack::Role', :key=>:id_role
6
+
7
+ end
8
+ end # module BlackStack
@@ -0,0 +1,234 @@
1
+ module BlackStack
2
+
3
+ #
4
+ class WorkerJob < Sequel::Model(:workerjob)
5
+
6
+ end
7
+
8
+ #
9
+ class Worker < Sequel::Model(:worker)
10
+ include BlackStack::BaseWorker
11
+ BlackStack::Worker.dataset = BlackStack::Worker.dataset.disable_insert_output
12
+ many_to_one :division, :class=>:'BlackStack::Division', :key=>:id_division
13
+ many_to_one :user, :class=>:'BlackStack::User', :key=>:id_user
14
+ =begin
15
+ # deprecated
16
+ # Actualiza la la lista de workers que estan asignados esta division
17
+ def self.updateAllFromCentral()
18
+ uri = URI("#{WORKER_API_SERVER_URL}/api1.3/pampa/get_all.json")
19
+ res = Net::HTTP.post_form(uri, {:api_key => BlackStack::Pampa::api_key,})
20
+ parsed = JSON.parse(res.body)
21
+ if (parsed['status'] != "success")
22
+ raise parsed['status'].to_s
23
+ else
24
+ parsed['workers'].each { |worker|
25
+ if ( worker['division_name']!=DATABASE )
26
+ q = "UPDATE worker SET active=0, division_name='#{worker['division_name']}' WHERE name='#{worker['name']}'"
27
+ DB.execute(q)
28
+ else # worker['division_name']==DIVISION_NAME
29
+
30
+ worker = BlackStack::Worker.where(:name=>worker['name']).first
31
+ if (worker==nil)
32
+ worker = BlackStack::Worker.new()
33
+ worker.id = worker['id']
34
+ worker.name = worker['name'].to_s
35
+ worker.last_ping_time = now() # esta fecha es actualiada por el mismo worker, para indicar que esta vivo y trabajando
36
+ worker.id_division = worker['id_division']
37
+ worker.process = worker['assigned_process']
38
+ worker.assigned_process = worker['assigned_process']
39
+ worker.id_object = worker['id_object']
40
+ worker.division_name = worker['division_name']
41
+ worker.save()
42
+ else
43
+ #puts "update" ?
44
+ end
45
+
46
+ DB.execute("UPDATE worker SET active=1 WHERE name='#{worker['name'].to_s}'")
47
+
48
+ if (worker['id_division'] != nil)
49
+ DB.execute("UPDATE worker SET id_division='#{worker['id_division'].to_s}' WHERE name='#{worker['name'].to_s}'")
50
+ end
51
+
52
+ if (worker['assigned_process'] != nil)
53
+ DB.execute("UPDATE worker SET process='#{worker['assigned_process'].to_s}', assigned_process='#{worker['assigned_process'].to_s}' WHERE name='#{worker['name'].to_s}'")
54
+ end
55
+
56
+ if (worker['id_object'] != nil)
57
+ DB.execute("UPDATE worker SET id_object='#{worker['id_object'].to_s}' WHERE name='#{worker['name'].to_s}'")
58
+ end
59
+
60
+ if (worker['division_name'] != nil)
61
+ DB.execute("UPDATE worker SET division_name='#{worker['division_name'].to_s}' WHERE name='#{worker['name'].to_s}'")
62
+ end
63
+
64
+ if (worker['type']==nil || worker['type'].to_i==MyProcess::TYPE_LOCAL)
65
+ DB.execute("UPDATE worker SET type=#{MyProcess::TYPE_LOCAL.to_s} WHERE name='#{worker['name'].to_s}'")
66
+ else
67
+ DB.execute("UPDATE worker SET type=#{MyProcess::TYPE_REMOTE.to_s} WHERE name='#{worker['name'].to_s}'")
68
+ end
69
+ end
70
+
71
+ # release resources
72
+ DB.disconnect
73
+ GC.start
74
+ }
75
+
76
+ end
77
+ end
78
+
79
+ # actualiza el rol y objeto asignado a este worker
80
+ def updateFromCentral()
81
+ uri = URI("#{WORKER_API_SERVER_URL}/api1.3/pampa/get.json")
82
+ res = Net::HTTP.post_form(uri, {'api_key' => BlackStack::Pampa::api_key, 'name' => self.name})
83
+ parsed = JSON.parse(res.body)
84
+ if (parsed['status'] != "success")
85
+ raise parsed['status'].to_s
86
+ else
87
+ # map response
88
+ self.id_division = parsed['id_division']
89
+ self.assigned_process = parsed['assigned_process']
90
+ self.id_object = parsed['id_object']
91
+ self.division_name = parsed['division_name']
92
+ self.active = true
93
+
94
+ if (parsed['id_object'].to_s.size>0)
95
+ aux_id_object = "'#{parsed['id_object']}'"
96
+ else
97
+ aux_id_object = "NULL"
98
+ end
99
+
100
+ # NOTA: DEBO HACER EL UPDATE POR FUERA DE SQUEL, DEBIDO AL BUG DE MAPEO DE SEQUEL
101
+ q =
102
+ "UPDATE worker SET " +
103
+ "active=1, id_division='#{parsed['id_division']}', assigned_process='#{parsed['assigned_process'].to_s.gsub("'","''")}', id_object=#{aux_id_object}, division_name='#{parsed['division_name'].to_s.gsub("'","''")}' " +
104
+ "WHERE id='#{self.id}'"
105
+ DB.execute(q)
106
+ end
107
+ end
108
+
109
+ # actualiza el rol y objeto asignado a cada worker asignado a esta division
110
+ def self.updateActivesFromCentral()
111
+ BlackStack::Worker.getActives().each { |worker|
112
+ worker.updateFromCentral()
113
+ }
114
+ end
115
+ =end
116
+
117
+ #
118
+ def factory(name, params)
119
+ w = BlackStack::Worker.where(:name=>name).first
120
+ if (w==nil)
121
+ w = BlackStack::Worker.new
122
+ end
123
+ w.id = parsed['id']
124
+ w.name = name
125
+ w.assigned_process = parsed['assigned_process']
126
+ w.id_object = parsed['id_object']
127
+ w.id_division = parsed['id_division']
128
+ w.division_name = parsed['division_name']
129
+ w.ws_url = parsed['ws_url']
130
+ w.ws_port = parsed['ws_port']
131
+ w.save
132
+ end
133
+
134
+ # Retorna true si este worker esta corriendo en nuestros propios servidores,
135
+ # Retorna false si este worker esta correiendo en otro host, asumiendo que es el host del cliente.
136
+ # Comparando la pulic_ip_address del worer con la lista en BlackStack::Pampa::set_farm_external_ip_addresses.
137
+ def hosted?
138
+ BlackStack::Pampa::set_farm_external_ip_addresses.inlude?(self.public_ip_address)
139
+ end # hosted?
140
+
141
+ # Si es un worker hosteado en nuestos servidores (ver metodo hosted?),
142
+ # => retorna la cantidad de dias que fa
143
+ def expirationDesc
144
+ s = "(unknown)"
145
+ if self.hosted?
146
+ if !self.expiration_time.nil?
147
+ s = DB["SELECT DATEDIFF(mi, GETDATE(), w.expiration_time) AS n FROM worker w WHERE w.id='#{self.id}'"].first[:n].to_i.to_time_spent
148
+ end
149
+ else # no hosted
150
+ s = "(self-hosted)"
151
+ end
152
+ s
153
+ end
154
+
155
+ # Retorna la cantidad de minutos desde que este worker envio una senial de vida.
156
+ # Este metodo se usa para saber si un worker esta activo o no.
157
+ def last_ping_minutes()
158
+ q = "SELECT DATEDIFF(mi, p.last_ping_time, getdate()) AS minutes FROM worker p WHERE p.id='#{self.id}'"
159
+ return DB[q].first[:minutes].to_i
160
+ end
161
+
162
+ # returns true if this worker had got a ping within the last 5 minutes
163
+ def active?
164
+ self.last_ping_minutes < BlackStack::BaseWorker::KEEP_ACTIVE_MINUTES
165
+ end
166
+
167
+ # escribe en el archivo de log de este worker
168
+ def log(s, level=1, is_error=false)
169
+ logw(s, self.process, self.id, level, is_error)
170
+ end
171
+
172
+ # envia una senial de vida a la division
173
+ # TODO: guardar fecha-hora del ultimo ping en un atributo privado, y evitar el acceso escesivo a la base de datos
174
+ def ping()
175
+ DB.execute("UPDATE worker SET last_ping_time=GETDATE() WHERE id='#{self.id}'")
176
+ end
177
+
178
+ # DEPRECATED
179
+ def self.getActivesCount(processName)
180
+ raise "Method needs some code inside."
181
+ end
182
+
183
+ # obtiene array de workers actives, filtrados por proceso y por tipo de worker.
184
+ def self.getActives(assigned_process_name=nil, worker_name_filter=nil)
185
+ a = Array.new
186
+ q = ""
187
+ if (assigned_process_name!=nil)
188
+ q =
189
+ "SELECT p.id AS [id] " +
190
+ "FROM worker p WITH (NOLOCK INDEX(IX_peer__process__last_ping_time)) " +
191
+ "WHERE last_ping_time>DATEADD(mi,-5,GETDATE()) " +
192
+ "AND ISNULL(active,0)=1 " + # active indica si este worker fue asignado a esta division en la central
193
+ "AND assigned_process='#{assigned_process_name}' "
194
+
195
+ if worker_name_filter != nil
196
+ q = q +
197
+ "AND p.name LIKE '%#{worker_name_filter.to_s}%' "
198
+ end
199
+
200
+ q = q +
201
+ "ORDER BY p.name "
202
+ DB[q].all do |row|
203
+ a << BlackStack::Worker.where(:id=>row[:id]).first
204
+ end
205
+ else
206
+ q =
207
+ "SELECT p.id AS [id] " +
208
+ "FROM worker p WITH (NOLOCK INDEX(IX_peer__process__last_ping_time)) " +
209
+ "WHERE last_ping_time>DATEADD(mi,-5,GETDATE()) " +
210
+ "AND ISNULL(active,0)=1 "
211
+
212
+ if worker_name_filter != nil
213
+ q = q +
214
+ "AND p.name LIKE '%#{worker_name_filter.to_s}%' "
215
+ end
216
+
217
+ q = q +
218
+ "ORDER BY p.name "
219
+ DB[q].all do |row|
220
+ a << BlackStack::Worker.where(:id=>row[:id]).first
221
+ end
222
+ end
223
+
224
+ return a
225
+ end
226
+
227
+ # obtiene cantidad de registros en cola para incrawl.lnsearchvariation
228
+ def getPendingLnSearchVariationBlockInCrawlCount()
229
+ return DB.from(:lnsearchvariationblock).where(:incrawl_reservation_id=>self.id, :incrawl_start_time=>nil).count
230
+ end
231
+
232
+ end # class Worker
233
+
234
+ end # module BlackStack