1
0
Эх сурвалжийг харах

feat: add submission status change attributes

trgiangdo 7 сар өмнө
parent
commit
0f6afb33ff

+ 41 - 0
taipy/core/submission/submission.py

@@ -139,6 +139,47 @@ class Submission(_Entity, _Labeled):
     def creation_date(self):
         return self._creation_date
 
+    @property
+    @_self_reload(_MANAGER_NAME)
+    def submitted_time(self) -> Optional[datetime]:
+        jobs_submitted_time = [job.submitted_time for job in self.jobs if job.submitted_time]
+        if jobs_submitted_time:
+            return min(jobs_submitted_time)
+        return None
+
+    @property
+    @_self_reload(_MANAGER_NAME)
+    def run_time(self) -> Optional[datetime]:
+        jobs_run_time = [job.run_time for job in self.jobs if job.run_time]
+        if jobs_run_time:
+            return min(jobs_run_time)
+        return None
+
+    @property
+    @_self_reload(_MANAGER_NAME)
+    def finished_time(self) -> Optional[datetime]:
+        if all(job.finished_time for job in self.jobs):
+            return max([job.finished_time for job in self.jobs if job.finished_time])
+        return None
+
+    @property
+    @_self_reload(_MANAGER_NAME)
+    def execution_duration(self) -> Optional[float]:
+        """Get the duration of the submission execution in seconds.
+        The execution time is the duration from the first job running to the last job completion.
+
+        Returns:
+            Optional[float]: The duration of the job execution in seconds.
+                - If no job was run, None is returned.
+                - If one of the jobs is not finished, the execution time is the duration
+                  from the running time of the first job to the current time.
+        """
+        if self.finished_time and self.run_time:
+            return (self.finished_time - self.run_time).total_seconds()
+        elif self.run_time and self.finished_time is None:
+            return (datetime.now() - self.run_time).total_seconds()
+        return None
+
     def get_label(self) -> str:
         """Returns the submission simple label prefixed by its owner label.
 

+ 10 - 0
tests/core/_orchestrator/test_orchestrator__submit.py

@@ -542,6 +542,11 @@ def test_submit_duration_development_mode():
     assert jobs_1s.execution_duration >= 1
     assert jobs_2s.execution_duration >= 2
 
+    assert submission.execution_duration >= 3
+    assert submission.submitted_time == min(jobs_1s.submitted_time, jobs_2s.submitted_time)
+    assert submission.run_time == min(jobs_1s.run_time, jobs_2s.run_time)
+    assert submission.finished_time == max(jobs_1s.finished_time, jobs_2s.finished_time)
+
 
 @pytest.mark.standalone
 def test_submit_duration_standalone_mode():
@@ -573,3 +578,8 @@ def test_submit_duration_standalone_mode():
     jobs_2s = jobs[0] if jobs[0].task.config_id == "task_config_id_2" else jobs[1]
     assert jobs_1s.execution_duration >= 1
     assert jobs_2s.execution_duration >= 2
+
+    assert submission.execution_duration >= 2  # Both tasks are executed in parallel so the duration may smaller than 3
+    assert submission.submitted_time == min(jobs_1s.submitted_time, jobs_2s.submitted_time)
+    assert submission.run_time == min(jobs_1s.run_time, jobs_2s.run_time)
+    assert submission.finished_time == max(jobs_1s.finished_time, jobs_2s.finished_time)

+ 38 - 0
tests/core/submission/test_submission.py

@@ -11,6 +11,7 @@
 
 from datetime import datetime
 
+import freezegun
 import pytest
 
 from taipy.core import TaskId
@@ -903,3 +904,40 @@ def test_is_finished():
     submission.submission_status = SubmissionStatus.COMPLETED
     assert submission.submission_status == SubmissionStatus.COMPLETED
     assert submission.is_finished()
+
+
+def test_execution_duration():
+    task = Task(config_id="task_1", properties={}, function=print, id=TaskId("task_1"))
+    submission = Submission(task.id, task._ID_PREFIX, task.config_id, properties={})
+    job_1 = Job("job_1", task, submission.id, submission.entity_id)
+    job_2 = Job("job_2", task, submission.id, submission.entity_id)
+
+    _TaskManagerFactory._build_manager()._set(task)
+    _SubmissionManagerFactory._build_manager()._set(submission)
+    _JobManagerFactory._build_manager()._set(job_1)
+    _JobManagerFactory._build_manager()._set(job_2)
+
+    submission.jobs = [job_1, job_2]
+    _SubmissionManagerFactory._build_manager()._set(submission)
+
+    with freezegun.freeze_time("2024-09-25 13:30:35"):
+        job_1.running()
+        job_2.pending()
+
+    assert submission.run_time == datetime(2024, 9, 25, 13, 30, 35)
+    assert submission.execution_duration > 0
+
+    with freezegun.freeze_time("2024-09-25 13:33:45"):
+        job_1.completed()
+        job_2.running()
+        assert submission.execution_duration == 190  # = 13:33:45 - 13:30:35
+        assert submission.run_time == datetime(2024, 9, 25, 13, 30, 35)
+
+        # Job 2 is not completed, so the submission is not completed
+        assert submission.finished_time is None
+
+    with freezegun.freeze_time("2024-09-25 13:35:50"):
+        job_2.completed()
+
+    assert submission.finished_time == datetime(2024, 9, 25, 13, 35, 50)
+    assert submission.execution_duration == 315  # = 13:35:50 - 13:30:35