Commit 90c118be8a1cd3d744bbee0a64b0ed008861825d

Authored by Etienne Pallier
1 parent 36b5f53e
Exists in dev

Implémentation complète du "Command state diag"

Showing 3 changed files with 46 additions and 43 deletions   Show diff stats
README.md
... ... @@ -67,13 +67,13 @@ This software has been tested and validated with the following configurations :
67 67 --------------------------------------------------------------------------------------------
68 68 ## LAST VERSION
69 69  
70   -Date: 01/04/2019
  70 +Date: 02/04/2019
71 71  
72 72 Author: E. Pallier
73 73  
74   -VERSION: 0.20.35
  74 +VERSION: 0.20.36
75 75  
76   -Comment: TODO ??? Agent sender peut marquer "expired" une commande qu'il a envoyée
  76 +Comment: Implémentation complète du "Command state diag"
77 77  
78 78 - Scenario de test :
79 79 - lancer agents A et B en mode simu (option -t): ./pyros.py -t start agentA,agentB
... ...
src/agent/Agent.py
... ... @@ -273,7 +273,7 @@ class Agent:
273 273 (OLD SYNTAX)
274 274 @startuml
275 275 title
276   - __** Agent.run() function activity diagram **__
  276 + __** (OLD) Agent.run() function activity diagram **__
277 277 end title
278 278  
279 279 (*) --> DO_EXIT=False & DO_RESTART=True
... ...
src/common/models.py
... ... @@ -342,7 +342,7 @@ class Command(models.Model):
342 342 PENDING --> EXPIRED: **command is too old**
343 343  
344 344 ' --- (2) RUNNING, SKIPPED, or EXPIRED ---
345   - RUNNING: + r_launched_time
  345 + RUNNING: + r_start_time
346 346 RUNNING --> PROCESSED : **finished**
347 347 RUNNING --> KILLED: \l**aborted** \n(by sender or other allowed agent, \nwith command "abort" or "exit")
348 348  
... ... @@ -350,14 +350,14 @@ class Command(models.Model):
350 350 SKIPPED --> [*]
351 351  
352 352 EXPIRED --> [*]
353   - EXPIRED: + expired_time \n+ author_agent_name
  353 + EXPIRED: + expired_time \n+ killer_agent_name
354 354  
355 355 ' --- (3) PROCESSED or KILLED ---
356   - PROCESSED: + finished_time
  356 + PROCESSED: + end_time
357 357 PROCESSED --> [*]
358 358  
359 359 KILLED --> [*]
360   - KILLED: + finished_time \n+ author_agent_name
  360 + KILLED: + end_time \n+ killer_agent_name
361 361  
362 362 @enduml
363 363 """
... ... @@ -404,27 +404,30 @@ class Command(models.Model):
404 404 sender = models.CharField(max_length=50, help_text='sender agent name', null=False)
405 405 recipient = models.CharField(max_length=50, help_text='recipient agent name', null=False)
406 406 # Other agent (than sender or recipient) that set this command to KILLED or EXPIRED
407   - author_agent_name = models.CharField(max_length=50, help_text='sender agent name', null=True)
  407 + killer_agent_name = models.CharField(max_length=50, help_text='sender agent name', null=True)
408 408 name = models.CharField(max_length=400, help_text='command name', null=False)
409 409 validity_duration = models.PositiveIntegerField('(in sec)', default=COMMANDS_VALIDITY_DURATION_SEC_DEFAULT)
  410 + #state = models.CharField(choices = CMD_STATUS_CODES, default=CMD_STATUS_CODES.CMD_PENDING, max_length=20)
  411 + state = models.CharField(choices = CMD_STATUS_CODES, default=CMD_STATUS_CODES.CMD_PENDING, max_length=20)
  412 + #state = models.IntegerField(choices=CMD_STATUS_CODES, default=RSCODE_PENDING)
410 413  
411 414 # (AUTO on create) Automatically set at table line creation (line created by the sender)
412 415 s_deposit_time = models.DateTimeField(blank=True, null=True, auto_now_add=True)
413 416 # Set by the recipient :
414 417 # - on reading:
415 418 r_read_time = models.DateTimeField(null=True)
  419 + # - on launching:
  420 + #r_start_time = models.DateTimeField(null=True)
  421 + r_start_time = models.DateTimeField(null=True)
416 422 # - on skipping (because idle):
417 423 r_skipped_time = models.DateTimeField(null=True)
418 424 # - on expiration (because too old):
419   - r_skipped_time = models.DateTimeField(null=True)
420   - # - on launching:
421   - r_launched_time = models.DateTimeField(null=True)
422   - # - after kill or execution:
  425 + #expired_time = models.DateTimeField(null=True)
  426 + # - after kill or execution or expiration:
423 427 #r_processed_time = models.DateTimeField(null=True)
424   - finished_time = models.DateTimeField(null=True)
  428 + #end_time = models.DateTimeField(null=True)
  429 + end_time = models.DateTimeField(null=True)
425 430  
426   - r_status_code = models.CharField(choices = CMD_STATUS_CODES, default=CMD_STATUS_CODES.CMD_PENDING, max_length=20)
427   - #r_status_code = models.IntegerField(choices=CMD_STATUS_CODES, default=RSCODE_PENDING)
428 431 # TODO: maybe à mettre au format json (key:value)
429 432 result = models.CharField(max_length=400, blank=True)
430 433  
... ... @@ -466,7 +469,7 @@ class Command(models.Model):
466 469 # only commands for agent agent_name
467 470 recipient = agent_name,
468 471 # only running commands
469   - r_status_code = cls.CMD_STATUS_CODES.CMD_RUNNING,
  472 + state = cls.CMD_STATUS_CODES.CMD_RUNNING,
470 473 # only not expired commands
471 474 #s_deposit_time__gte = cls.get_peremption_date_from_now(),
472 475 )
... ... @@ -492,7 +495,7 @@ class Command(models.Model):
492 495 # only commands for agent agent_name
493 496 recipient = agent_name,
494 497 # only running commands
495   - r_status_code = cls.CMD_STATUS_CODES.CMD_PENDING,
  498 + state = cls.CMD_STATUS_CODES.CMD_PENDING,
496 499 # except very recent commands : take only commands that are more than 2 sec old
497 500 s_deposit_time__lt = now_minus_2sec
498 501 )
... ... @@ -507,7 +510,7 @@ class Command(models.Model):
507 510 return cls.objects.filter(
508 511 # only pending commands
509 512 # but also including the currently running command
510   - Q(r_status_code = cls.CMD_STATUS_CODES.CMD_PENDING) | Q(r_status_code = cls.CMD_STATUS_CODES.CMD_RUNNING),
  513 + Q(state = cls.CMD_STATUS_CODES.CMD_PENDING) | Q(state = cls.CMD_STATUS_CODES.CMD_RUNNING),
511 514 # only commands for agent agent_name
512 515 recipient = agent_name,
513 516 # only not expired commands
... ... @@ -555,7 +558,7 @@ class Command(models.Model):
555 558 # only expired commands
556 559 s_deposit_time__lt = cls.get_peremption_date_from_now(),
557 560 ).exclude(
558   - r_status_code = cls.CMD_STATUS_CODES.CMD_RUNNING
  561 + state = cls.CMD_STATUS_CODES.CMD_RUNNING
559 562 )
560 563 if old_commands.exists():
561 564 print("Found old commands to delete:")
... ... @@ -578,7 +581,7 @@ class Command(models.Model):
578 581 # -------------- Command INSTANCE METHODS --------------
579 582  
580 583 def __str__(self):
581   - return (f"Commmand '{self.name}' ({self.r_status_code}) sent by agent {self.sender} to agent {self.recipient} at {self.s_deposit_time}")
  584 + return (f"Commmand '{self.name}' ({self.state}) sent by agent {self.sender} to agent {self.recipient} at {self.s_deposit_time}")
582 585  
583 586 # --- BOOLEAN (test) functions ---
584 587  
... ... @@ -601,20 +604,20 @@ class Command(models.Model):
601 604 return self.r_read_time is not None
602 605  
603 606 def is_pending(self):
604   - return self.r_status_code == self.CMD_STATUS_CODES.CMD_PENDING
  607 + return self.state == self.CMD_STATUS_CODES.CMD_PENDING
605 608  
606 609 def is_running(self):
607 610 #return (datetime.utcnow() - self.s_deposit_time) > timedelta(seconds = self.validity_duration)
608   - return self.r_status_code == self.CMD_STATUS_CODES.CMD_RUNNING
  611 + return self.state == self.CMD_STATUS_CODES.CMD_RUNNING
609 612  
610 613 def is_executed(self):
611   - return self.r_status_code == self.CMD_STATUS_CODES.CMD_EXECUTED
  614 + return self.state == self.CMD_STATUS_CODES.CMD_EXECUTED
612 615  
613 616 def is_skipped(self):
614   - return self.r_status_code == self.CMD_STATUS_CODES.CMD_SKIPPED
  617 + return self.state == self.CMD_STATUS_CODES.CMD_SKIPPED
615 618  
616 619 def is_killed(self):
617   - return self.r_status_code == self.CMD_STATUS_CODES.CMD_KILLED
  620 + return self.state == self.CMD_STATUS_CODES.CMD_KILLED
618 621  
619 622 def is_expired(self):
620 623 #return (datetime.utcnow() - self.s_deposit_time) > timedelta(seconds = self.validity_duration)
... ... @@ -646,61 +649,61 @@ class Command(models.Model):
646 649  
647 650 def set_as_processed(self):
648 651 print(f"- Set command {self.name} as processed")
649   - self.set_status_to(self.CMD_STATUS_CODES.CMD_EXECUTED)
  652 + self.set_state_to(self.CMD_STATUS_CODES.CMD_EXECUTED)
650 653 #print(self)
651 654 """
652   - self.r_status_code = self.CMD_STATUS_CODES.CMD_EXECUTED
  655 + self.state = self.CMD_STATUS_CODES.CMD_EXECUTED
653 656 self.r_processed_time = datetime.utcnow().astimezone()
654 657 self.save()
655 658 """
656 659 # Optimization: update the related fields, but does not work, why ?
657   - ##self.save(update_fields=["r_status_code", "r_processed_time"])
  660 + ##self.save(update_fields=["state", "r_processed_time"])
658 661  
659 662 def set_as_outofdate(self):
660 663 print(f"- Set this command as expired (older than its validity duration of {self.validity_duration}s): {self}")
661   - self.set_status_to(self.CMD_STATUS_CODES.CMD_OUTOFDATE)
  664 + self.set_state_to(self.CMD_STATUS_CODES.CMD_OUTOFDATE)
662 665  
663 666 def set_as_pending(self):
664   - self.set_status_to(self.CMD_STATUS_CODES.CMD_PENDING)
  667 + self.set_state_to(self.CMD_STATUS_CODES.CMD_PENDING)
665 668  
666 669 def set_as_skipped(self):
667   - self.set_status_to(self.CMD_STATUS_CODES.CMD_SKIPPED)
  670 + self.set_state_to(self.CMD_STATUS_CODES.CMD_SKIPPED)
668 671  
669 672 def set_as_killed_by(self, author_agent:str):
670 673 print(f"- Set command {self.name} as killed")
671 674 #print(f"- Set this command as killed: {self}")
672   - self.set_status_to(self.CMD_STATUS_CODES.CMD_KILLED, author_agent)
  675 + self.set_state_to(self.CMD_STATUS_CODES.CMD_KILLED, author_agent)
673 676  
674 677 def set_as_running(self):
675 678 print(f"- Set command {self.name} as running")
676   - self.set_status_to(self.CMD_STATUS_CODES.CMD_RUNNING)
  679 + self.set_state_to(self.CMD_STATUS_CODES.CMD_RUNNING)
677 680 '''
678 681 def set_as_executed(self):
679   - self.set_status_to(self.CMD_STATUS_CODES.CMD_EXECUTED)
  682 + self.set_state_to(self.CMD_STATUS_CODES.CMD_EXECUTED)
680 683 '''
681 684  
682   - def set_status_to(self, status:str, author_agent_name:str=None):
  685 + def set_state_to(self, status:str, author_agent_name:str=None):
683 686 now_time = datetime.utcnow().astimezone()
684 687 if status in (self.CMD_STATUS_CODES.CMD_RUNNING, self.CMD_STATUS_CODES.CMD_SKIPPED, self.CMD_STATUS_CODES.CMD_OUTOFDATE):
685 688 assert self.is_pending()
686 689 if status == self.CMD_STATUS_CODES.CMD_RUNNING:
687   - self.r_launched_time = now_time
  690 + self.r_start_time = now_time
688 691 elif status == self.CMD_STATUS_CODES.CMD_SKIPPED:
689 692 self.r_skipped_time = now_time
690 693 # EXPIRED
691 694 elif status == self.CMD_STATUS_CODES.CMD_OUTOFDATE:
692   - self.expired_time = now_time
693   - self.author_agent_name = author_agent_name
  695 + self.end_time = now_time
  696 + self.killer_agent_name = author_agent_name
694 697 elif status in (self.CMD_STATUS_CODES.CMD_EXECUTED, self.CMD_STATUS_CODES.CMD_KILLED):
695 698 assert self.is_running()
696   - self.finished_time = now_time
  699 + self.end_time = now_time
697 700 if status == self.CMD_STATUS_CODES.CMD_KILLED:
698   - self.author_agent_name = author_agent_name
  701 + self.killer_agent_name = author_agent_name
699 702 # Update command status
700   - self.r_status_code = status
  703 + self.state = status
701 704 self.save()
702 705 # Optimization, but does not work, why ?...
703   - ##self.save(update_fields=["r_status_code"])
  706 + ##self.save(update_fields=["state"])
704 707  
705 708  
706 709  
... ...