14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
17
- from logging import INFO
18
17
import logging
18
+ from logging import INFO
19
19
from typing import (
20
20
Iterable ,
21
21
List ,
25
25
26
26
import pytest
27
27
28
+ from cylc .flow import LOG
28
29
from cylc .flow .commands import (
30
+ force_trigger_tasks ,
29
31
run_cmd ,
30
- force_trigger_tasks
31
32
)
32
- from cylc .flow import LOG
33
33
from cylc .flow .data_messages_pb2 import (
34
+ PbJob ,
34
35
PbPrerequisite ,
35
36
PbTaskProxy ,
36
37
)
42
43
TASKS ,
43
44
WORKFLOW ,
44
45
)
45
- from cylc .flow .id import TaskTokens , Tokens
46
+ from cylc .flow .id import (
47
+ TaskTokens ,
48
+ Tokens ,
49
+ )
46
50
from cylc .flow .network .log_stream_handler import ProtobufStreamHandler
47
51
from cylc .flow .scheduler import Scheduler
48
52
from cylc .flow .task_events_mgr import TaskEventsManager
51
55
TASK_OUTPUT_SUBMITTED ,
52
56
TASK_OUTPUT_SUCCEEDED ,
53
57
)
58
+ from cylc .flow .task_proxy import TaskProxy
54
59
from cylc .flow .task_state import (
55
60
TASK_STATUS_FAILED ,
56
61
TASK_STATUS_PREPARING ,
@@ -125,6 +130,11 @@ def get_pb_prereqs(schd: 'Scheduler') -> 'List[PbPrerequisite]':
125
130
]
126
131
127
132
133
+ def get_pb_job (schd : Scheduler , itask : TaskProxy ) -> PbJob :
134
+ """Get the protobuf job for a given task from the data store."""
135
+ return schd .data_store_mgr .data [schd .id ][JOBS ][itask .job_tokens .id ]
136
+
137
+
128
138
@pytest .fixture (scope = 'module' )
129
139
async def mod_harness (mod_flow , mod_scheduler , mod_start ):
130
140
flow_def = {
@@ -832,9 +842,6 @@ async def test_log_events(one: Scheduler, start):
832
842
833
843
async def test_no_backwards_job_state_change (one : Scheduler , start ):
834
844
"""It should not allow backwards job state changes."""
835
- def get_job_state (itask ):
836
- return one .data_store_mgr .data [one .id ][JOBS ][itask .job_tokens .id ].state
837
-
838
845
async with start (one ):
839
846
itask = one .pool .get_tasks ()[0 ]
840
847
itask .state_reset (TASK_STATUS_PREPARING )
@@ -843,9 +850,59 @@ def get_job_state(itask):
843
850
844
851
one .task_events_mgr .process_message (itask , INFO , TASK_OUTPUT_STARTED )
845
852
await one .update_data_structure ()
846
- assert get_job_state ( itask ) == TASK_STATUS_RUNNING
853
+ assert get_pb_job ( one , itask ). state == TASK_STATUS_RUNNING
847
854
848
855
# Simulate late arrival of "submitted" message
849
856
one .task_events_mgr .process_message (itask , INFO , TASK_OUTPUT_SUBMITTED )
850
857
await one .update_data_structure ()
851
- assert get_job_state (itask ) == TASK_STATUS_RUNNING
858
+ assert get_pb_job (one , itask ).state == TASK_STATUS_RUNNING
859
+
860
+
861
+ async def test_job_estimated_finish_time (one_conf , flow , scheduler , start ):
862
+ """It should set estimated_finish_time on job elements along with
863
+ started_time."""
864
+ wid = flow ({
865
+ ** one_conf ,
866
+ 'scheduler' : {'UTC mode' : True },
867
+ 'runtime' : {
868
+ 'one' : {'execution time limit' : 'PT2M' },
869
+ },
870
+ })
871
+ schd : Scheduler = scheduler (wid )
872
+ date = '2081-07-02T'
873
+
874
+ async def start_job (itask : TaskProxy , start_time : str ):
875
+ if not schd .pool .get_task (itask .point , itask .tdef .name ):
876
+ schd .pool .add_to_pool (itask )
877
+ await schd .update_data_structure ()
878
+ itask .state_reset (TASK_STATUS_PREPARING )
879
+ itask .submit_num += 1
880
+ itask .jobs = []
881
+ schd .task_events_mgr .process_message (
882
+ itask , INFO , TASK_OUTPUT_SUBMITTED # submit time irrelevant
883
+ )
884
+ await schd .update_data_structure ()
885
+ schd .task_events_mgr .process_message (
886
+ itask , INFO , TASK_OUTPUT_STARTED , f'{ date } { start_time } '
887
+ )
888
+ await schd .update_data_structure ()
889
+
890
+ async with start (schd ):
891
+ itask = schd .pool .get_tasks ()[0 ]
892
+ await start_job (itask , '06:00:00Z' )
893
+ # 1st job: estimate based on execution time limit:
894
+ assert (
895
+ get_pb_job (schd , itask ).estimated_finish_time
896
+ == f'{ date } 06:02:00Z'
897
+ )
898
+
899
+ # Finish this job and start a new one:
900
+ schd .task_events_mgr .process_message (
901
+ itask , INFO , TASK_OUTPUT_SUCCEEDED , f'{ date } 06:00:40Z'
902
+ )
903
+ await start_job (itask , '06:01:00Z' )
904
+ # >=2nd job: estimate based on mean of previous jobs:
905
+ assert (
906
+ get_pb_job (schd , itask ).estimated_finish_time
907
+ == f'{ date } 06:01:40Z'
908
+ )
0 commit comments