@@ -893,10 +893,14 @@ def _schedule_terminalization_retry(self, *, active: _ActiveTask) -> None:
893893 self ._handoff_retry_tasks .add (retry_task )
894894 retry_task .add_done_callback (self ._handoff_retry_tasks .discard )
895895
896+ def _can_retry_active_run (self , * , scenario_result_id : str ) -> bool :
897+ """Return whether retry work may continue for the active run."""
898+ return not self ._stopping and self ._active_scenario_result_id == scenario_result_id
899+
896900 async def _retry_handoff_async (self , * , scenario_result_id : str ) -> None :
897901 """Retry scheduler handoff with bounded exponential delay until it succeeds or shutdown begins."""
898902 delay = _SCHEDULER_RETRY_INITIAL_SECONDS
899- while not self ._stopping and self . _active_scenario_result_id == scenario_result_id :
903+ while self ._can_retry_active_run ( scenario_result_id = scenario_result_id ) :
900904 await asyncio .sleep (delay )
901905 try :
902906 await self ._handoff_scheduler_async (scenario_result_id = scenario_result_id )
@@ -909,11 +913,11 @@ async def _retry_handoff_async(self, *, scenario_result_id: str) -> None:
909913 async def _retry_terminalization_async (self , * , active : _ActiveTask ) -> None :
910914 """Retry a failed cancellation transition, then perform the terminal handoff."""
911915 delay = _SCHEDULER_RETRY_INITIAL_SECONDS
912- while not self ._stopping and self . _active_scenario_result_id == active .scenario_result_id :
916+ while self ._can_retry_active_run ( scenario_result_id = active .scenario_result_id ) :
913917 await asyncio .sleep (delay )
914918 try :
915919 async with self ._scheduler_lock :
916- if self . _stopping or self ._active_scenario_result_id != active .scenario_result_id :
920+ if not self ._can_retry_active_run ( scenario_result_id = active .scenario_result_id ) :
917921 return
918922 await asyncio .to_thread (
919923 self ._memory .try_update_scenario_run_state ,
@@ -1447,6 +1451,16 @@ def _load_started_at(*, scenario_result: ScenarioResult) -> datetime | None:
14471451 return None
14481452 return started_at if started_at .tzinfo is not None else None
14491453
1454+ @staticmethod
1455+ def _identifier_techniques (scenario_identifier : ScenarioIdentifier | None ) -> list [str ]:
1456+ """
1457+ Read techniques when legacy persisted metadata has an identifier.
1458+
1459+ Returns:
1460+ list[str]: Stored techniques or an empty list.
1461+ """
1462+ return list (scenario_identifier .techniques or []) if scenario_identifier is not None else []
1463+
14501464 @staticmethod
14511465 def _safe_run_metadata (
14521466 * ,
@@ -1793,10 +1807,8 @@ def get_run_progress_from_storage(
17931807 target , datasets_used , scenario_parameters = self ._safe_run_metadata (scenario_identifier = scenario_identifier )
17941808 if plan is not None :
17951809 techniques_used = list (dict .fromkeys (group .display_group for group in plan .atomic_groups ))
1796- elif scenario_identifier is not None :
1797- techniques_used = list (scenario_identifier .techniques or [])
17981810 else :
1799- techniques_used = []
1811+ techniques_used = self . _identifier_techniques ( scenario_identifier )
18001812 return ScenarioRunProgress (
18011813 run = ScenarioProgressHeader (
18021814 scenario_result_id = scenario_result_id ,
0 commit comments