From 3381a718aa9e021a4a7c8d84155f4c82615f2159 Mon Sep 17 00:00:00 2001 From: Etienne Pallier Date: Wed, 6 Mar 2019 12:32:39 +0100 Subject: [PATCH] Agent : command purge_commands() implemented --- README.md | 6 +++--- src/agent/Agent.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- src/common/models.py | 18 ++++++++++++++++++ 3 files changed, 70 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 5e133b5..d7e4918 100644 --- a/README.md +++ b/README.md @@ -67,14 +67,14 @@ This software has been tested and validated with the following configurations : -------------------------------------------------------------------------------------------- ## LAST VERSION -Date: 05/03/2019 +Date: 06/03/2019 Author: E. Pallier -VERSION: 0.20.6 +VERSION: 0.20.7 Comment: - Agent : agentX working with a command simulator + Agent : command purge_commands() implemented -------------------------------------------------------------------------------------------- diff --git a/src/agent/Agent.py b/src/agent/Agent.py index 565adf8..f95e721 100644 --- a/src/agent/Agent.py +++ b/src/agent/Agent.py @@ -10,7 +10,7 @@ VERSION = "0.4" #from __future__ import absolute_import import time -import datetime +from datetime import datetime, timedelta import os @@ -90,15 +90,12 @@ class Agent: SIMULATOR_MODE = True SIMULATOR_COMMANDS = iter([ "go_active", - "go_idle", - "go_active", "go_idle", + "specific_not_executed_because_idle", "go_active", - - "specific_1", - "specific_2", + "specific_executed_because_not_idle", "stop" ]) @@ -106,10 +103,12 @@ class Agent: #_current_test_cmd = None #_nb_test_cmds = 0 - # Run for real, otherwise just print messages without really doing anything FOR_REAL = True + #COMMANDS_PEREMPTION_HOURS = 48 + COMMANDS_PEREMPTION_HOURS = 60/60 + name = "Generic Agent" mainloop_waittime = 3 subloop_waittime = 2 @@ -133,6 +132,7 @@ class Agent: _agent_survey = None + _iter_num = 0 def __init__(self, name:str=None, config_filename:str=None): self.set_mode(self.MODE_IDLE) @@ -202,16 +202,13 @@ class Agent: # Main loop while True: - self.set_status(self.STATUS_MAIN_LOOP) - - """ - A chaque tour de boucle, remplir champ "iamalive" avec timestamp + durée validité (> temps iteration, n minutes par défaut) - + nom agent dans table agents_survey (nom agent + mode + status + updated timestamp) - """ print() print() - print("Starting main loop iteration...") + #print("-"*80) + + print("-"*20, f"MAIN LOOP ITERATION {self._iter_num} (START)", "-"*20) + self.set_status(self.STATUS_MAIN_LOOP) self.show_mode_and_status() self.load_config() @@ -241,14 +238,40 @@ class Agent: if cmd: self.specific_process(cmd) print("---") + # Every N iterations, delete old commands + N=3 + if (self._iter_num % N) == 0: self.purge_commands() + self.waitfor(self.mainloop_waittime) - print("Ending main loop iteration...") + print("-"*20, "MAIN LOOP ITERATION (END)", "-"*20) + #print("-"*80) #self.do_log(LOG_DEBUG, "Ending main loop iteration") + self._iter_num += 1 + def purge_commands(self): + """ + Delete commands (which I am recipient of) older than COMMANDS_PEREMPTION_HOURS (like 48h) + + NB: datetime.utcnow() is equivalent to datetime.now(timezone.utc) + """ + + COMMAND_PEREMPTION_DATE_FROM_NOW = datetime.utcnow() - timedelta(hours = self.COMMANDS_PEREMPTION_HOURS) + print("peremption date", COMMAND_PEREMPTION_DATE_FROM_NOW) + old_commands = Command.objects.filter( + # only commands for me + receiver = self.name, + # only pending commands + sender_deposit_time__lt = COMMAND_PEREMPTION_DATE_FROM_NOW, + ) + if old_commands.exists(): + print("Found old commands to delete:") + for cmd in old_commands: print(cmd) + old_commands.delete() + def waitfor(self, nbsec): print(f"Now, waiting for {nbsec} seconds...") time.sleep(nbsec) @@ -423,9 +446,8 @@ class Agent: print(cmd) # 3) Update read time to say that the command has been READ - assert cmd.receiver_read_time is None # f"Command {cmd} should not have been already read !!" - cmd.receiver_read_time = datetime.datetime.now() - cmd.save() + ##assert cmd.receiver_read_time is None # f"Command {cmd} should not have been already read !!" + cmd.set_as_read() return cmd @@ -439,22 +461,18 @@ class Agent: # If expired command, change its status to expired and return elapsed_time = cmd.receiver_read_time - cmd.sender_deposit_time - max_time = datetime.timedelta(seconds = cmd.validity_duration_sec) + max_time = timedelta(seconds = cmd.validity_duration_sec) print(f"Elapsed time is {elapsed_time}, (max is {max_time})") if elapsed_time > max_time: print("This command is expired, so mark it as expired, and ignore it") #cmd.delete() - cmd.receiver_status_code = Command.CMD_STATUS_CODES.CMD_OUTOFDATE - cmd.save() + cmd.set_as_outofdate() return None # If cmd is generic, execute it, change its status to executed, and return if cmd.is_generic(): print("This command is generic, execute it...") self.exec_generic_cmd(cmd) - print("...Generic cmd has been executed") - cmd.receiver_status_code = Command.CMD_STATUS_CODES.CMD_EXECUTED - cmd.save() if cmd.command == "stop": exit(0) return None @@ -463,8 +481,7 @@ class Agent: # cmd is not generic but, as I am idle, change its status to SKIPPED, ignore it, and return if self.mode == self.MODE_IDLE: print("This command is not generic but, as I am IDLE, I mark it SKIPPED and ignore it") - cmd.receiver_status_code = Command.CMD_STATUS_CODES.CMD_SKIPPED - cmd.save() + cmd.set_as_skipped() return None # 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: def exec_generic_cmd(self, cmd:Command): - time.sleep(1) + cmd.set_as_running() + # Executing command if cmd.command == "go_active": self.set_active() elif cmd.command == "go_idle": self.set_idle() elif cmd.command == "stop": pass + time.sleep(1) + cmd.set_as_executed() + print("...Generic cmd has been executed") + def do_log(self): diff --git a/src/common/models.py b/src/common/models.py index 9b1131f..ebc796c 100644 --- a/src/common/models.py +++ b/src/common/models.py @@ -1,6 +1,7 @@ ##from __future__ import unicode_literals from enum import Enum +from datetime import datetime from django.contrib.auth.models import AbstractUser from django.db import models @@ -276,6 +277,23 @@ class Command(models.Model): """ return self.command in self.GENERIC_COMMANDS + def set_as_read(self): + self.receiver_read_time = datetime.utcnow() + self.save() + + def set_as_outofdate(self): + self.set_status_to(self.CMD_STATUS_CODES.CMD_OUTOFDATE) + def set_as_skipped(self): + self.set_status_to(self.CMD_STATUS_CODES.CMD_SKIPPED) + def set_as_running(self): + self.set_status_to(self.CMD_STATUS_CODES.CMD_RUNNING) + def set_as_executed(self): + self.set_status_to(self.CMD_STATUS_CODES.CMD_EXECUTED) + + def set_status_to(self, status:str): + self.receiver_status_code = status + self.save() + class AgentSurvey(models.Model): """ -- libgit2 0.21.2