Commit 90c118be8a1cd3d744bbee0a64b0ed008861825d
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
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 | ... | ... |