From 2cac63e32fb09074e47ad14ec64ba5ea201bfbe2 Mon Sep 17 00:00:00 2001
From: Jorrit Schaap <schaap@astron.nl>
Date: Tue, 19 Oct 2021 10:59:16 +0200
Subject: [PATCH] TMSS-1116: ignore obsolete predecessors when scheduling

---
 .../src/tmss/tmssapp/models/scheduling.py     |  5 +++++
 SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py |  5 +++++
 SAS/TMSS/backend/test/t_scheduling.py         | 19 ++++++++++++++++++-
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py b/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py
index 1d743ff33d7..9f1dc953a20 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py
@@ -172,6 +172,11 @@ class Subtask(BasicCommon, ProjectPropertyMixin, TemplateSchemaMixin):
             else:
                 self.__original_obsolete_since = None
 
+    @property
+    def is_obsolete(self) -> bool:
+        '''convenience property turning the obsolete_since timestamp into a boolean'''
+        return self.obsolete_since is not None
+
     @property
     def duration(self) -> timedelta:
         '''the duration of this subtask (stop-start), or 0 if start/stop are None'''
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py b/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py
index 7b1d1931bb2..0c699a9536f 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py
@@ -1101,6 +1101,11 @@ def check_prerequities_for_scheduling(subtask: Subtask) -> bool:
 
     for predecessor in subtask.predecessors.all():
         if predecessor.state.value != SubtaskState.Choices.FINISHED.value:
+            if predecessor.is_obsolete:
+                logger.info("Ignoring subtask id=%s's predecessor id=%s with state='%s' while scheduling because it is marked obsolete",
+                            subtask.pk, predecessor.pk, predecessor.state.value)
+                continue
+
             raise SubtaskSchedulingException("Cannot schedule subtask id=%d because its predecessor id=%s in not FINISHED but state=%s"
                                              % (subtask.pk, predecessor.pk, predecessor.state.value))
 
diff --git a/SAS/TMSS/backend/test/t_scheduling.py b/SAS/TMSS/backend/test/t_scheduling.py
index 1968b2e9113..92da7f2e8d7 100755
--- a/SAS/TMSS/backend/test/t_scheduling.py
+++ b/SAS/TMSS/backend/test/t_scheduling.py
@@ -466,11 +466,28 @@ class SchedulingTest(unittest.TestCase):
                                                                 "preprocessing pipeline",
                                                                 {})
 
+            # cancel the observation
             obs_subtask = client.cancel_subtask(obs_subtask['id'])
+
+            # check, should be cancelled, but not obsolete
             self.assertEqual('cancelled', obs_subtask['state_value'])
+            self.assertIsNone(obs_subtask['obsolete_since'])
 
-            pipe_subtask = client.schedule_subtask(pipe_subtask['id'])
+            # scheduling pipeline should fail
+            with self.assertRaises(Exception) as context:
+                pipe_subtask = client.schedule_subtask(pipe_subtask['id'])
+                self.assertTrue('Cannot schedule subtask' in str(context.exception))
+                self.assertTrue('not FINISHED but state=cancelled' in str(context.exception))
+
+            # now mark the cancelled observation as obsolete
+            obs_subtask = client.mark_subtask_as_obsolete(obs_subtask['id'])
 
+            # check, should (still) be cancelled, and now obsolete
+            self.assertEqual('cancelled', obs_subtask['state_value'])
+            self.assertIsNotNone(obs_subtask['obsolete_since'])
+
+            # scheduling pipeline should now be a success
+            pipe_subtask = client.schedule_subtask(pipe_subtask['id'])
             self.assertEqual('scheduled', pipe_subtask['state_value'])
             self.assertEqual('scheduled', tmss_test_env.ra_test_environment.radb.getTask(tmss_id=pipe_subtask['id'])['status'])
 
-- 
GitLab