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 ,
@@ -127,6 +132,11 @@ def get_pb_prereqs(schd: 'Scheduler') -> 'List[PbPrerequisite]':
127
132
]
128
133
129
134
135
+ def get_pb_job (schd : Scheduler , itask : TaskProxy ) -> PbJob :
136
+ """Get the protobuf job for a given task from the data store."""
137
+ return schd .data_store_mgr .data [schd .id ][JOBS ][itask .job_tokens .id ]
138
+
139
+
130
140
@pytest .fixture (scope = 'module' )
131
141
async def mod_harness (mod_flow , mod_scheduler , mod_start ):
132
142
flow_def = {
@@ -834,9 +844,6 @@ async def test_log_events(one: Scheduler, start):
834
844
835
845
async def test_no_backwards_job_state_change (one : Scheduler , start ):
836
846
"""It should not allow backwards job state changes."""
837
- def get_job_state (itask ):
838
- return one .data_store_mgr .data [one .id ][JOBS ][itask .job_tokens .id ].state
839
-
840
847
async with start (one ):
841
848
itask = one .pool .get_tasks ()[0 ]
842
849
itask .state_reset (TASK_STATUS_PREPARING )
@@ -845,9 +852,59 @@ def get_job_state(itask):
845
852
846
853
one .task_events_mgr .process_message (itask , INFO , TASK_OUTPUT_STARTED )
847
854
await one .update_data_structure ()
848
- assert get_job_state ( itask ) == TASK_STATUS_RUNNING
855
+ assert get_pb_job ( one , itask ). state == TASK_STATUS_RUNNING
849
856
850
857
# Simulate late arrival of "submitted" message
851
858
one .task_events_mgr .process_message (itask , INFO , TASK_OUTPUT_SUBMITTED )
852
859
await one .update_data_structure ()
853
- assert get_job_state (itask ) == TASK_STATUS_RUNNING
860
+ assert get_pb_job (one , itask ).state == TASK_STATUS_RUNNING
861
+
862
+
863
+ async def test_job_estimated_finish_time (one_conf , flow , scheduler , start ):
864
+ """It should set estimated_finish_time on job elements along with
865
+ started_time."""
866
+ wid = flow ({
867
+ ** one_conf ,
868
+ 'scheduler' : {'UTC mode' : True },
869
+ 'runtime' : {
870
+ 'one' : {'execution time limit' : 'PT2M' },
871
+ },
872
+ })
873
+ schd : Scheduler = scheduler (wid )
874
+ date = '2081-07-02T'
875
+
876
+ async def start_job (itask : TaskProxy , start_time : str ):
877
+ if not schd .pool .get_task (itask .point , itask .tdef .name ):
878
+ schd .pool .add_to_pool (itask )
879
+ await schd .update_data_structure ()
880
+ itask .state_reset (TASK_STATUS_PREPARING )
881
+ itask .submit_num += 1
882
+ itask .jobs = []
883
+ schd .task_events_mgr .process_message (
884
+ itask , INFO , TASK_OUTPUT_SUBMITTED # submit time irrelevant
885
+ )
886
+ await schd .update_data_structure ()
887
+ schd .task_events_mgr .process_message (
888
+ itask , INFO , TASK_OUTPUT_STARTED , f'{ date } { start_time } '
889
+ )
890
+ await schd .update_data_structure ()
891
+
892
+ async with start (schd ):
893
+ itask = schd .pool .get_tasks ()[0 ]
894
+ await start_job (itask , '06:00:00Z' )
895
+ # 1st job: estimate based on execution time limit:
896
+ assert (
897
+ get_pb_job (schd , itask ).estimated_finish_time
898
+ == f'{ date } 06:02:00Z'
899
+ )
900
+
901
+ # Finish this job and start a new one:
902
+ schd .task_events_mgr .process_message (
903
+ itask , INFO , TASK_OUTPUT_SUCCEEDED , f'{ date } 06:00:40Z'
904
+ )
905
+ await start_job (itask , '06:01:00Z' )
906
+ # >=2nd job: estimate based on mean of previous jobs:
907
+ assert (
908
+ get_pb_job (schd , itask ).estimated_finish_time
909
+ == f'{ date } 06:01:40Z'
910
+ )
0 commit comments