Skip to content

Commit 2ec98dd

Browse files
wxtimoliver-sandershjoliver
authored
Made execution time limit unsettable by reload or broadcast. (#5902)
* Made execution time limit unsettable by reload or broadcast. Formerly a suppress statement was supressing cases when we wanted to set itask.summary['execution time limit'] = None. Added tests. * response to verbal review * Apply suggestions from code review Co-authored-by: Oliver Sanders <[email protected]> * Prevent false positives in test for broadcast. Test broadcast using _prep_submit_task_job rather than _prep_submit_task_job_impl so that the fake broadcast is applied. * Update changes.d/5902.fix.md Co-authored-by: Hilary James Oliver <[email protected]> * made function less tolerant --------- Co-authored-by: Oliver Sanders <[email protected]> Co-authored-by: Hilary James Oliver <[email protected]>
1 parent 9948532 commit 2ec98dd

File tree

3 files changed

+89
-5
lines changed

3 files changed

+89
-5
lines changed

changes.d/5902.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a bug that prevented unsetting `execution time limit` by broadcast or reload.

cylc/flow/task_job_mgr.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
)
3737
from shutil import rmtree
3838
from time import time
39-
from typing import TYPE_CHECKING, Optional
39+
from typing import TYPE_CHECKING, Any, Union, Optional
4040

4141
from cylc.flow import LOG
4242
from cylc.flow.job_runner_mgr import JobPollContext
@@ -1262,10 +1262,11 @@ def _prep_submit_task_job_impl(self, workflow, itask, rtconfig):
12621262
itask.submit_num] = itask.platform['name']
12631263

12641264
itask.summary['job_runner_name'] = itask.platform['job runner']
1265-
with suppress(TypeError):
1266-
itask.summary[self.KEY_EXECUTE_TIME_LIMIT] = float(
1267-
rtconfig['execution time limit']
1268-
)
1265+
1266+
# None is an allowed non-float number for Execution time limit.
1267+
itask.summary[
1268+
self.KEY_EXECUTE_TIME_LIMIT
1269+
] = self.get_execution_time_limit(rtconfig['execution time limit'])
12691270

12701271
# Location of job file, etc
12711272
self._create_job_log_path(workflow, itask)
@@ -1281,6 +1282,30 @@ def _prep_submit_task_job_impl(self, workflow, itask, rtconfig):
12811282
job_d=job_d
12821283
)
12831284

1285+
@staticmethod
1286+
def get_execution_time_limit(
1287+
config_execution_time_limit: Any
1288+
) -> Union[None, float]:
1289+
"""Get execution time limit from config and process it.
1290+
1291+
If the etl from the config is a Falsy then return None.
1292+
Otherwise try and parse value as float.
1293+
1294+
Examples:
1295+
>>> from pytest import raises
1296+
>>> this = TaskJobManager.get_execution_time_limit
1297+
1298+
>>> this(None)
1299+
>>> this("54")
1300+
54.0
1301+
>>> this({})
1302+
>>> with raises(ValueError):
1303+
... this('🇳🇿')
1304+
"""
1305+
if config_execution_time_limit:
1306+
return float(config_execution_time_limit)
1307+
return None
1308+
12841309
def get_job_conf(
12851310
self,
12861311
workflow,

tests/integration/test_task_job_mgr.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# You should have received a copy of the GNU General Public License
1515
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17+
from contextlib import suppress
1718
import logging
1819
from typing import Any as Fixture
1920

@@ -128,3 +129,60 @@ async def test__run_job_cmd_logs_platform_lookup_fail(
128129
warning = caplog.records[-1]
129130
assert warning.levelname == 'ERROR'
130131
assert 'Unable to run command jobs-poll' in warning.msg
132+
133+
134+
async def test__prep_submit_task_job_impl_handles_execution_time_limit(
135+
flow: Fixture,
136+
scheduler: Fixture,
137+
start: Fixture,
138+
):
139+
"""Ensure that emptying the execution time limit unsets it.
140+
141+
Previously unsetting the etl by either broadcast or reload
142+
would not unset a previous etl.
143+
144+
See https://github.com/cylc/cylc-flow/issues/5891
145+
"""
146+
id_ = flow({
147+
"scheduling": {
148+
"cycling mode": "integer",
149+
"graph": {"R1": "a"}
150+
},
151+
"runtime": {
152+
"root": {},
153+
"a": {
154+
"script": "sleep 10",
155+
"execution time limit": 'PT5S'
156+
}
157+
}
158+
})
159+
160+
# Run in live mode - function not called in sim mode.
161+
schd = scheduler(id_, run_mode='live')
162+
async with start(schd):
163+
task_a = schd.pool.get_tasks()[0]
164+
# We're not interested in the job file stuff, just
165+
# in the summary state.
166+
with suppress(FileExistsError):
167+
schd.task_job_mgr._prep_submit_task_job_impl(
168+
schd.workflow, task_a, task_a.tdef.rtconfig)
169+
assert task_a.summary['execution_time_limit'] == 5.0
170+
171+
# If we delete the etl it gets deleted in the summary:
172+
task_a.tdef.rtconfig['execution time limit'] = None
173+
with suppress(FileExistsError):
174+
schd.task_job_mgr._prep_submit_task_job_impl(
175+
schd.workflow, task_a, task_a.tdef.rtconfig)
176+
assert not task_a.summary.get('execution_time_limit', '')
177+
178+
# put everything back and test broadcast too.
179+
task_a.tdef.rtconfig['execution time limit'] = 5.0
180+
task_a.summary['execution_time_limit'] = 5.0
181+
schd.broadcast_mgr.broadcasts = {
182+
'1': {'a': {'execution time limit': None}}}
183+
with suppress(FileExistsError):
184+
# We run a higher level function here to ensure
185+
# that the broadcast is applied.
186+
schd.task_job_mgr._prep_submit_task_job(
187+
schd.workflow, task_a)
188+
assert not task_a.summary.get('execution_time_limit', '')

0 commit comments

Comments
 (0)