Skip to content

Commit a4111d0

Browse files
authored
Merge pull request #6868 from cylc/8.4.x
8.4.x sync (manual redo after botched file name under changes.d).
2 parents 85e4f4c + bba6f72 commit a4111d0

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

changes.d/6856.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a niche bug where outputs of a task could be wiped from the database if it was subsequently suicide triggered (e.g, if a custom output was manually set before the suicide trigger occurred).

cylc/flow/task_pool.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1870,7 +1870,11 @@ def spawn_task(
18701870
for cycle, task, output in self.abs_outputs_done
18711871
])
18721872

1873-
self.db_add_new_flow_rows(itask)
1873+
if prev_status is None:
1874+
# only add new flow rows if this task has not run before
1875+
# see https://github.com/cylc/cylc-flow/pull/6821
1876+
self.db_add_new_flow_rows(itask)
1877+
18741878
return itask
18751879

18761880
def _spawn_after_flow_wait(self, itask: TaskProxy) -> None:

tests/integration/test_task_pool.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
TASK_OUTPUT_FAILED,
4747
TASK_OUTPUT_SUCCEEDED,
4848
)
49+
from cylc.flow.task_pool import TaskPool
4950
from cylc.flow.task_state import (
5051
TASK_STATUS_EXPIRED,
5152
TASK_STATUS_FAILED,
@@ -2464,3 +2465,75 @@ async def test_start_tasks(
24642465
"2050/baz",
24652466
])
24662467
)
2468+
2469+
2470+
async def test_add_new_flow_rows_on_spawn(
2471+
flow,
2472+
scheduler,
2473+
run,
2474+
complete,
2475+
db_select,
2476+
capcall,
2477+
) -> None:
2478+
"""Task suicide should not override previously completed outputs.
2479+
2480+
See https://github.com/cylc/cylc-flow/pull/6821
2481+
"""
2482+
# capture all TaskPool.spawn_task() calls
2483+
spawn_task_calls = capcall(
2484+
'cylc.flow.task_pool.TaskPool.spawn_task', TaskPool.spawn_task
2485+
)
2486+
2487+
def list_spawn_task_calls():
2488+
"""Return a list of the names of tasks which have been run through the
2489+
"spawn_tasks" function so far."""
2490+
return [
2491+
args[1] for args, _kwargs in spawn_task_calls
2492+
]
2493+
2494+
id_ = flow({
2495+
'scheduling': {
2496+
'graph': {
2497+
'R1': '''
2498+
slow:fail? => foo
2499+
slow? => !foo
2500+
foo:x => x
2501+
''',
2502+
},
2503+
},
2504+
'runtime': {
2505+
'foo': {
2506+
'outputs': {'x': 'xxx'}
2507+
},
2508+
},
2509+
})
2510+
2511+
schd = scheduler(id_, paused_start=False)
2512+
async with run(schd):
2513+
# 1/slow should spawn on startup
2514+
assert list_spawn_task_calls() == ['slow']
2515+
2516+
# set foo:x
2517+
await commands.run_cmd(
2518+
commands.set_prereqs_and_outputs(
2519+
schd, ['1/foo'], ['1'], ['x'], None
2520+
)
2521+
)
2522+
# 1/foo:x should be recorded in the DB:
2523+
assert db_select(
2524+
schd, True, 'task_outputs', 'outputs', cycle='1', name='foo'
2525+
) == [('{"x": "(manually completed)"}',)]
2526+
# and 1/x should spawn:
2527+
assert list_spawn_task_calls() == ['slow', 'x']
2528+
2529+
# run the workflow until completion
2530+
await complete(schd, timeout=5)
2531+
2532+
# 1/foo should spawn as a result of the suicide trigger
2533+
assert list_spawn_task_calls() == ['slow', 'x', 'foo']
2534+
2535+
# the manually completed output should not have been overwritten by the
2536+
# suicide trigger
2537+
assert db_select(
2538+
schd, True, 'task_outputs', 'outputs', cycle='1', name='foo'
2539+
) == [('{"x": "(manually completed)"}',)]

0 commit comments

Comments
 (0)