diff --git a/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py index 4a5fb15b1db2ef8670b5e336ffbb4d95145f3181..4b7e8d8a523ed69b47183ee3006818990fb70e83 100644 --- a/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py +++ b/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py @@ -326,47 +326,53 @@ class Scheduler: while lower_bound < upper_bound: self._raise_if_triggered() - # find and schedule the next best unit - # ignore/exclude as candidates the unit(s) which are already scheduled in this round. - # when new candidates are overlapping with already scheduled units, they are re-evaluated to see who wins. - logger.info("do_dynamic_schedule: lower_bound='%s' upper_bound='%s' already_scheduled_and_thus_to_be_ignored_units: %s", - lower_bound, upper_bound, - ",".join([str(s.id) for s in sorted(list(scheduled_units), key=id)])) - - scheduled_unit = self.schedule_next_scheduling_unit(lower_bound, - min(lower_bound + timedelta(hours=24), upper_bound), - exclude_units=scheduled_units) + try: + # find and schedule the next best unit + # ignore/exclude as candidates the unit(s) which are already scheduled in this round. + # when new candidates are overlapping with already scheduled units, they are re-evaluated to see who wins. + logger.info("do_dynamic_schedule: lower_bound='%s' upper_bound='%s' already_scheduled_and_thus_to_be_ignored_units: %s", + lower_bound, upper_bound, + ",".join([str(s.id) for s in sorted(list(scheduled_units), key=id)])) - if scheduled_unit: - scheduled_units.append(scheduled_unit) + scheduled_unit = self.schedule_next_scheduling_unit(lower_bound, + min(lower_bound + timedelta(hours=24), upper_bound), + exclude_units=scheduled_units) - # schedule any related unit(s) - scheduled_units.extend(self.try_schedule_relational_units(scheduled_unit)) + if scheduled_unit: + scheduled_units.append(scheduled_unit) - try: - # see if we can fit any B-prio units in the new gap(s) in the schedule? - scheduled_B_units = self.schedule_B_priority_units_in_gaps_around_scheduling_unit(scheduled_unit, exclude_units=scheduled_units, lower_bound=lower_bound, upper_bound=upper_bound) - scheduled_units.extend(scheduled_B_units) - except Exception as e: - logger.exception(e) - else: - # advance window and search again - lower_bound += timedelta(minutes=60) + # schedule any related unit(s) + scheduled_units.extend(self.try_schedule_relational_units(scheduled_unit)) - # for nice "visual" feedback to the user, move each "old" schedulable unit to the lower_bound - # this also indicates to the user that the unit has been considered for times < lower_bound, and they could not be scheduled there. - for unit in get_dynamically_schedulable_scheduling_units().filter(scheduled_start_time__lt=lower_bound).all(): try: - update_subtasks_start_times_for_scheduling_unit(unit, lower_bound) + # see if we can fit any B-prio units in the new gap(s) in the schedule? + scheduled_B_units = self.schedule_B_priority_units_in_gaps_around_scheduling_unit(scheduled_unit, exclude_units=scheduled_units, lower_bound=lower_bound, upper_bound=upper_bound) + scheduled_units.extend(scheduled_B_units) except Exception as e: - logger.warning("update_subtasks_start_times_for_scheduling_unit: %s", str(e)) - - # any units left to be scheduled? If so, loop again, else break out of while loop - if not get_dynamically_schedulable_scheduling_units().exists(): - # there are no more schedulable units. check to-be-re-evaluated scheduled future units. - if not get_scheduled_scheduling_units(lower_bound, upper_bound, 'dynamic').exists(): - # there are no more to-be-re-evaluated scheduled future units. - break + logger.exception(e) + else: + # advance window and search again + lower_bound += timedelta(minutes=60) + + # for nice "visual" feedback to the user, move each "old" schedulable unit to the lower_bound + # this also indicates to the user that the unit has been considered for times < lower_bound, and they could not be scheduled there. + for unit in get_dynamically_schedulable_scheduling_units().filter(scheduled_start_time__lt=lower_bound).all(): + try: + update_subtasks_start_times_for_scheduling_unit(unit, lower_bound) + except Exception as e: + logger.warning("update_subtasks_start_times_for_scheduling_unit: %s", str(e)) + + # any units left to be scheduled? If so, loop again, else break out of while loop + if not get_dynamically_schedulable_scheduling_units().exists(): + # there are no more schedulable units. check to-be-re-evaluated scheduled future units. + if not get_scheduled_scheduling_units(lower_bound, upper_bound, 'dynamic').exists(): + # there are no more to-be-re-evaluated scheduled future units. + break + except Exception as e: + if isinstance(SchedulerInterruptedException): + raise + else: + logger.exception("do_dynamic_schedule: %s", str(e)) logger.info("do_dynamic_schedule: finished updating dynamic schedule")