Skip to content

Commit 8b5257a

Browse files
task_events_mgr: task events should not be able to re-wind task state.
* Closes #7269 * This fixes a bug where a delayed poll notification could cause a final-state task to re-wind to submitted/running.
1 parent a84ad35 commit 8b5257a

2 files changed

Lines changed: 49 additions & 14 deletions

File tree

cylc/flow/task_events_mgr.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
TASK_STATUS_SUCCEEDED,
121121
TASK_STATUS_WAITING,
122122
TASK_STATUSES_ACTIVE,
123+
TASK_STATUSES_FINAL,
123124
)
124125
from cylc.flow.wallclock import (
125126
get_current_time_string,
@@ -786,9 +787,7 @@ def process_message(
786787
)
787788

788789
if message == self.EVENT_STARTED:
789-
if flag == self.FLAG_RECEIVED and itask.state.is_gt(
790-
TASK_STATUS_RUNNING
791-
):
790+
if itask.state.is_gt(TASK_STATUS_RUNNING):
792791
# Already running.
793792
return True
794793
self._process_message_started(itask, event_time, forced)
@@ -803,10 +802,8 @@ def process_message(
803802
self.spawn_children(itask, TASK_OUTPUT_EXPIRED, forced)
804803

805804
elif task_output == self.EVENT_FAILED:
806-
if flag == self.FLAG_RECEIVED and itask.state.is_gt(
807-
TASK_STATUS_FAILED
808-
):
809-
# Already failed.
805+
if itask.state(*TASK_STATUSES_FINAL):
806+
# Already in a final state
810807
return True
811808
msg = self.JOB_FAILED
812809
if run_signal is not None:
@@ -829,20 +826,16 @@ def process_message(
829826
self.spawn_children(itask, TASK_OUTPUT_FAILED, forced)
830827

831828
elif message == self.EVENT_SUBMIT_FAILED:
832-
if flag == self.FLAG_RECEIVED and itask.state.is_gt(
833-
TASK_STATUS_SUBMIT_FAILED
834-
):
835-
# Already submit-failed
829+
if itask.state(*TASK_STATUSES_FINAL):
830+
# Already in a final state
836831
return True
837832
if forced or self._process_message_submit_failed(
838833
itask, event_time
839834
):
840835
self.spawn_children(itask, TASK_OUTPUT_SUBMIT_FAILED, forced)
841836

842837
elif message == self.EVENT_SUBMITTED:
843-
if flag == self.FLAG_RECEIVED and itask.state.is_gte(
844-
TASK_STATUS_SUBMITTED
845-
):
838+
if itask.state.is_gte(TASK_STATUS_SUBMITTED):
846839
# Already submitted.
847840
return True
848841
if not forced:

tests/integration/test_task_events_mgr.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@
2929
from cylc.flow.scheduler import Scheduler
3030
from cylc.flow.task_events_mgr import (
3131
EventKey,
32+
TaskEventsManager,
3233
TaskJobLogsRetrieveContext,
3334
)
35+
from cylc.flow.task_outputs import TASK_OUTPUT_STARTED
3436
from cylc.flow.task_state import (
3537
TASK_STATUS_PREPARING,
3638
TASK_STATUS_SUBMIT_FAILED,
39+
TASK_STATUS_SUCCEEDED,
3740
)
3841

3942
from cylc.flow.network.resolvers import TaskMsg
@@ -368,3 +371,42 @@ async def test_event_email_body(
368371
assert f'host: {mod_one.host}' in email_body
369372
assert f'port: {mod_one.server.port}' in email_body
370373
assert f'owner: {mod_one.owner}' in email_body
374+
375+
376+
@pytest.mark.parametrize(
377+
'message_flag',
378+
(
379+
TaskEventsManager.FLAG_POLLED,
380+
TaskEventsManager.FLAG_INTERNAL,
381+
TaskEventsManager.FLAG_RECEIVED,
382+
),
383+
)
384+
async def test_delayed_event_notification(
385+
message_flag,
386+
one_conf,
387+
flow,
388+
scheduler,
389+
run,
390+
complete,
391+
):
392+
"""Delated event notification should not cause task state to rewind.
393+
394+
One a task reaches a state, it should not be possible for that state to
395+
re-wind as the result of a subsequent event.
396+
397+
In this test, a task succeeds naturally, a "started" event is then sent
398+
using one of the configured flags. The task state should not re-wind as a
399+
result.
400+
401+
See https://github.com/cylc/cylc-flow/issues/7269
402+
"""
403+
id_ = flow(one_conf)
404+
schd = scheduler(id_, paused_start=False)
405+
async with run(schd):
406+
itask = schd.pool.get_tasks()[0]
407+
await complete(schd, itask.tokens.relative_id)
408+
assert itask.state.status == TASK_STATUS_SUCCEEDED
409+
schd.task_events_mgr.process_message(
410+
itask, 'INFO', TASK_OUTPUT_STARTED, flag=message_flag
411+
)
412+
assert itask.state.status == TASK_STATUS_SUCCEEDED

0 commit comments

Comments
 (0)