Commit 3381a718aa9e021a4a7c8d84155f4c82615f2159
1 parent
30b22ee6
Exists in
dev
Agent : command purge_commands() implemented
Showing
3 changed files
with
70 additions
and
30 deletions
Show diff stats
README.md
... | ... | @@ -67,14 +67,14 @@ This software has been tested and validated with the following configurations : |
67 | 67 | -------------------------------------------------------------------------------------------- |
68 | 68 | ## LAST VERSION |
69 | 69 | |
70 | -Date: 05/03/2019 | |
70 | +Date: 06/03/2019 | |
71 | 71 | |
72 | 72 | Author: E. Pallier |
73 | 73 | |
74 | -VERSION: 0.20.6 | |
74 | +VERSION: 0.20.7 | |
75 | 75 | |
76 | 76 | Comment: |
77 | - Agent : agentX working with a command simulator | |
77 | + Agent : command purge_commands() implemented | |
78 | 78 | |
79 | 79 | |
80 | 80 | -------------------------------------------------------------------------------------------- | ... | ... |
src/agent/Agent.py
... | ... | @@ -10,7 +10,7 @@ VERSION = "0.4" |
10 | 10 | #from __future__ import absolute_import |
11 | 11 | |
12 | 12 | import time |
13 | -import datetime | |
13 | +from datetime import datetime, timedelta | |
14 | 14 | import os |
15 | 15 | |
16 | 16 | |
... | ... | @@ -90,15 +90,12 @@ class Agent: |
90 | 90 | SIMULATOR_MODE = True |
91 | 91 | SIMULATOR_COMMANDS = iter([ |
92 | 92 | "go_active", |
93 | - "go_idle", | |
94 | 93 | |
95 | - "go_active", | |
96 | 94 | "go_idle", |
95 | + "specific_not_executed_because_idle", | |
97 | 96 | |
98 | 97 | "go_active", |
99 | - | |
100 | - "specific_1", | |
101 | - "specific_2", | |
98 | + "specific_executed_because_not_idle", | |
102 | 99 | |
103 | 100 | "stop" |
104 | 101 | ]) |
... | ... | @@ -106,10 +103,12 @@ class Agent: |
106 | 103 | #_current_test_cmd = None |
107 | 104 | #_nb_test_cmds = 0 |
108 | 105 | |
109 | - | |
110 | 106 | # Run for real, otherwise just print messages without really doing anything |
111 | 107 | FOR_REAL = True |
112 | 108 | |
109 | + #COMMANDS_PEREMPTION_HOURS = 48 | |
110 | + COMMANDS_PEREMPTION_HOURS = 60/60 | |
111 | + | |
113 | 112 | name = "Generic Agent" |
114 | 113 | mainloop_waittime = 3 |
115 | 114 | subloop_waittime = 2 |
... | ... | @@ -133,6 +132,7 @@ class Agent: |
133 | 132 | |
134 | 133 | _agent_survey = None |
135 | 134 | |
135 | + _iter_num = 0 | |
136 | 136 | |
137 | 137 | def __init__(self, name:str=None, config_filename:str=None): |
138 | 138 | self.set_mode(self.MODE_IDLE) |
... | ... | @@ -202,16 +202,13 @@ class Agent: |
202 | 202 | |
203 | 203 | # Main loop |
204 | 204 | while True: |
205 | - self.set_status(self.STATUS_MAIN_LOOP) | |
206 | - | |
207 | - """ | |
208 | - A chaque tour de boucle, remplir champ "iamalive" avec timestamp + durée validité (> temps iteration, n minutes par défaut) | |
209 | - + nom agent dans table agents_survey (nom agent + mode + status + updated timestamp) | |
210 | - """ | |
211 | 205 | |
212 | 206 | print() |
213 | 207 | print() |
214 | - print("Starting main loop iteration...") | |
208 | + #print("-"*80) | |
209 | + | |
210 | + print("-"*20, f"MAIN LOOP ITERATION {self._iter_num} (START)", "-"*20) | |
211 | + self.set_status(self.STATUS_MAIN_LOOP) | |
215 | 212 | self.show_mode_and_status() |
216 | 213 | |
217 | 214 | self.load_config() |
... | ... | @@ -241,14 +238,40 @@ class Agent: |
241 | 238 | if cmd: self.specific_process(cmd) |
242 | 239 | print("---") |
243 | 240 | |
241 | + # Every N iterations, delete old commands | |
242 | + N=3 | |
243 | + if (self._iter_num % N) == 0: self.purge_commands() | |
244 | + | |
244 | 245 | self.waitfor(self.mainloop_waittime) |
245 | 246 | |
246 | - print("Ending main loop iteration...") | |
247 | + print("-"*20, "MAIN LOOP ITERATION (END)", "-"*20) | |
248 | + #print("-"*80) | |
247 | 249 | |
248 | 250 | #self.do_log(LOG_DEBUG, "Ending main loop iteration") |
249 | 251 | |
252 | + self._iter_num += 1 | |
250 | 253 | |
251 | 254 | |
255 | + def purge_commands(self): | |
256 | + """ | |
257 | + Delete commands (which I am recipient of) older than COMMANDS_PEREMPTION_HOURS (like 48h) | |
258 | + | |
259 | + NB: datetime.utcnow() is equivalent to datetime.now(timezone.utc) | |
260 | + """ | |
261 | + | |
262 | + COMMAND_PEREMPTION_DATE_FROM_NOW = datetime.utcnow() - timedelta(hours = self.COMMANDS_PEREMPTION_HOURS) | |
263 | + print("peremption date", COMMAND_PEREMPTION_DATE_FROM_NOW) | |
264 | + old_commands = Command.objects.filter( | |
265 | + # only commands for me | |
266 | + receiver = self.name, | |
267 | + # only pending commands | |
268 | + sender_deposit_time__lt = COMMAND_PEREMPTION_DATE_FROM_NOW, | |
269 | + ) | |
270 | + if old_commands.exists(): | |
271 | + print("Found old commands to delete:") | |
272 | + for cmd in old_commands: print(cmd) | |
273 | + old_commands.delete() | |
274 | + | |
252 | 275 | def waitfor(self, nbsec): |
253 | 276 | print(f"Now, waiting for {nbsec} seconds...") |
254 | 277 | time.sleep(nbsec) |
... | ... | @@ -423,9 +446,8 @@ class Agent: |
423 | 446 | print(cmd) |
424 | 447 | |
425 | 448 | # 3) Update read time to say that the command has been READ |
426 | - assert cmd.receiver_read_time is None # f"Command {cmd} should not have been already read !!" | |
427 | - cmd.receiver_read_time = datetime.datetime.now() | |
428 | - cmd.save() | |
449 | + ##assert cmd.receiver_read_time is None # f"Command {cmd} should not have been already read !!" | |
450 | + cmd.set_as_read() | |
429 | 451 | return cmd |
430 | 452 | |
431 | 453 | |
... | ... | @@ -439,22 +461,18 @@ class Agent: |
439 | 461 | |
440 | 462 | # If expired command, change its status to expired and return |
441 | 463 | elapsed_time = cmd.receiver_read_time - cmd.sender_deposit_time |
442 | - max_time = datetime.timedelta(seconds = cmd.validity_duration_sec) | |
464 | + max_time = timedelta(seconds = cmd.validity_duration_sec) | |
443 | 465 | print(f"Elapsed time is {elapsed_time}, (max is {max_time})") |
444 | 466 | if elapsed_time > max_time: |
445 | 467 | print("This command is expired, so mark it as expired, and ignore it") |
446 | 468 | #cmd.delete() |
447 | - cmd.receiver_status_code = Command.CMD_STATUS_CODES.CMD_OUTOFDATE | |
448 | - cmd.save() | |
469 | + cmd.set_as_outofdate() | |
449 | 470 | return None |
450 | 471 | |
451 | 472 | # If cmd is generic, execute it, change its status to executed, and return |
452 | 473 | if cmd.is_generic(): |
453 | 474 | print("This command is generic, execute it...") |
454 | 475 | self.exec_generic_cmd(cmd) |
455 | - print("...Generic cmd has been executed") | |
456 | - cmd.receiver_status_code = Command.CMD_STATUS_CODES.CMD_EXECUTED | |
457 | - cmd.save() | |
458 | 476 | if cmd.command == "stop": exit(0) |
459 | 477 | return None |
460 | 478 | |
... | ... | @@ -463,8 +481,7 @@ class Agent: |
463 | 481 | # cmd is not generic but, as I am idle, change its status to SKIPPED, ignore it, and return |
464 | 482 | if self.mode == self.MODE_IDLE: |
465 | 483 | print("This command is not generic but, as I am IDLE, I mark it SKIPPED and ignore it") |
466 | - cmd.receiver_status_code = Command.CMD_STATUS_CODES.CMD_SKIPPED | |
467 | - cmd.save() | |
484 | + cmd.set_as_skipped() | |
468 | 485 | return None |
469 | 486 | |
470 | 487 | # Je suis pas idle et cde pas générique: je la traite pas, elle sera traitée par core_process : |
... | ... | @@ -475,10 +492,15 @@ class Agent: |
475 | 492 | |
476 | 493 | |
477 | 494 | def exec_generic_cmd(self, cmd:Command): |
478 | - time.sleep(1) | |
495 | + cmd.set_as_running() | |
496 | + # Executing command | |
479 | 497 | if cmd.command == "go_active": self.set_active() |
480 | 498 | elif cmd.command == "go_idle": self.set_idle() |
481 | 499 | elif cmd.command == "stop": pass |
500 | + time.sleep(1) | |
501 | + cmd.set_as_executed() | |
502 | + print("...Generic cmd has been executed") | |
503 | + | |
482 | 504 | |
483 | 505 | |
484 | 506 | def do_log(self): | ... | ... |
src/common/models.py
1 | 1 | ##from __future__ import unicode_literals |
2 | 2 | |
3 | 3 | from enum import Enum |
4 | +from datetime import datetime | |
4 | 5 | |
5 | 6 | from django.contrib.auth.models import AbstractUser |
6 | 7 | from django.db import models |
... | ... | @@ -276,6 +277,23 @@ class Command(models.Model): |
276 | 277 | """ |
277 | 278 | return self.command in self.GENERIC_COMMANDS |
278 | 279 | |
280 | + def set_as_read(self): | |
281 | + self.receiver_read_time = datetime.utcnow() | |
282 | + self.save() | |
283 | + | |
284 | + def set_as_outofdate(self): | |
285 | + self.set_status_to(self.CMD_STATUS_CODES.CMD_OUTOFDATE) | |
286 | + def set_as_skipped(self): | |
287 | + self.set_status_to(self.CMD_STATUS_CODES.CMD_SKIPPED) | |
288 | + def set_as_running(self): | |
289 | + self.set_status_to(self.CMD_STATUS_CODES.CMD_RUNNING) | |
290 | + def set_as_executed(self): | |
291 | + self.set_status_to(self.CMD_STATUS_CODES.CMD_EXECUTED) | |
292 | + | |
293 | + def set_status_to(self, status:str): | |
294 | + self.receiver_status_code = status | |
295 | + self.save() | |
296 | + | |
279 | 297 | |
280 | 298 | class AgentSurvey(models.Model): |
281 | 299 | """ | ... | ... |