diff --git a/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py index 428bc37d3f0cc91fdefe6384d2ab6cd02875eb34..f107a47b8ebb97185997b4def131ce7a53f9e4e1 100644 --- a/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py +++ b/SAS/TMSS/backend/services/scheduling/lib/dynamic_scheduling.py @@ -303,9 +303,9 @@ def get_scheduled_scheduling_units(lower:datetime=None, upper:datetime=None) -> '''get a list of all scheduling_units for which at least one 'independent' (with no predecessor like an observation) subtask is scheduled''' scheduled_subtasks = models.Subtask.independent_subtasks().filter(state__value='scheduled') if lower is not None: - scheduled_subtasks = scheduled_subtasks.filter(stop_time__gte=lower) + scheduled_subtasks = scheduled_subtasks.filter(scheduled_on_sky_stop_time__gte=lower) if upper is not None: - scheduled_subtasks = scheduled_subtasks.filter(start_time__lte=upper) + scheduled_subtasks = scheduled_subtasks.filter(scheduled_on_sky_start_time__lte=upper) return list(models.SchedulingUnitBlueprint.objects.filter(id__in=scheduled_subtasks.values('task_blueprint__scheduling_unit_blueprint_id').distinct()).all()) @@ -314,7 +314,7 @@ def get_running_observation_subtasks(stopping_after:datetime=None) -> [models.Su running_obs_subtasks = models.Subtask.objects.filter(state__value__in=[models.SubtaskState.Choices.STARTING.value, models.SubtaskState.Choices.STARTED.value], specifications_template__type__value=models.SubtaskType.Choices.OBSERVATION.value) if stopping_after is not None: - running_obs_subtasks = running_obs_subtasks.filter(stop_time__gte=stopping_after) + running_obs_subtasks = running_obs_subtasks.filter(scheduled_on_sky_stop_time__gte=stopping_after) return list(running_obs_subtasks.all()) diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py b/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py index f474f4d9b2085130564a7416b6b66c586aa53a6f..cf5ef9487464a1b5cea1bbc510f725fb5d8be821 100644 --- a/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py +++ b/SAS/TMSS/backend/src/tmss/tmssapp/models/scheduling.py @@ -21,6 +21,7 @@ from lofar.sas.tmss.tmss.exceptions import SubtaskSchedulingException, SubtaskIl from django.conf import settings from lofar.sas.resourceassignment.resourceassignmentservice.rpc import RADBRPC import uuid +from django.db.models.functions import Coalesce # # I/O @@ -289,6 +290,22 @@ class Subtask(BasicCommon, ProjectPropertyMixin, TemplateSchemaMixin): self.specifications_template.type.value, self.state)) + @property + def on_sky_start_time(self) -> datetime: + return self.scheduled_on_sky_start_time if self.actual_on_sky_start_time is None else self.actual_on_sky_start_time + + @property + def on_sky_stop_time(self) -> datetime: + return self.scheduled_on_sky_stop_time if self.actual_on_sky_stop_time is None else self.actual_on_sky_stop_time + + @property + def process_start_time(self) -> datetime: + return self.scheduled_process_start_time if self.actual_process_start_time is None else self.actual_process_start_time + + @property + def process_stop_time(self) -> datetime: + return self.scheduled_process_stop_time if self.actual_process_stop_time is None else self.actual_process_stop_time + def save(self, force_insert=False, force_update=False, using=None, update_fields=None): creating = self._state.adding # True on create, False on update diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/serializers/scheduling.py b/SAS/TMSS/backend/src/tmss/tmssapp/serializers/scheduling.py index 04a943b931347bfb24ce8103df8e4d170848167c..e41d21d8c8c2c5a3fffe60c677185c1e7cb45f4e 100644 --- a/SAS/TMSS/backend/src/tmss/tmssapp/serializers/scheduling.py +++ b/SAS/TMSS/backend/src/tmss/tmssapp/serializers/scheduling.py @@ -91,7 +91,7 @@ class SubtaskSerializer(DynamicRelationalHyperlinkedModelSerializer): class Meta: model = models.Subtask fields = '__all__' - extra_fields = ['input_dataproducts', 'output_dataproducts'] + extra_fields = ['input_dataproducts', 'output_dataproducts', 'on_sky_start_time', 'on_sky_stop_time', 'process_start_time', 'process_stop_time'] expandable_fields = { 'input_dataproducts': ('lofar.sas.tmss.tmss.tmssapp.serializers.DataproductSerializer', {'many': True}), 'output_dataproducts': ('lofar.sas.tmss.tmss.tmssapp.serializers.DataproductSerializer', {'many': True}) diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py b/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py index fa1ee8088b4d910737e91f135366b2a9c505df6d..cf1f3c9315765d0383271b44522de2fe29cae004 100644 --- a/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py +++ b/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py @@ -1482,6 +1482,10 @@ def schedule_observation_subtask(observation_subtask: Subtask): # step 5: set state to SCHEDULED (resulting in the qaservice to pick this subtask up and run it) observation_subtask.state = SubtaskState.objects.get(value=SubtaskState.Choices.SCHEDULED.value) + + # step 6: set scheduled_process_start/stop_time for MACScheduler + observation_subtask.scheduled_process_start_time = observation_subtask.scheduled_on_sky_start_time - timedelta(minutes=3) + observation_subtask.scheduled_process_stop_time = observation_subtask.scheduled_on_sky_stop_time + timedelta(minutes=1) observation_subtask.save() return observation_subtask diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/scheduling.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/scheduling.py index 18f108dd5cda6c215ba95869064dc99dd5293b8a..f59734365aa1f689a250a90a3d0a6992fd3251da 100644 --- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/scheduling.py +++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/scheduling.py @@ -39,7 +39,7 @@ from lofar.sas.tmss.tmss.tmssapp.renderers import PlainTextRenderer from rest_framework.views import APIView from rest_framework.decorators import api_view, renderer_classes from django.core.exceptions import ObjectDoesNotExist - +import django_property_filter as property_filters class TextPlainAutoSchema(SwaggerAutoSchema): def get_produces(self): @@ -131,12 +131,16 @@ class DataproductFeedbackTemplateViewSet(AbstractTemplateViewSet): serializer_class = serializers.DataproductFeedbackTemplateSerializer -class SubTaskFilter(filters.FilterSet): +class SubTaskFilter(property_filters.PropertyFilterSet): id = NumberInFilter(field_name='id', lookup_expr='in') id_min = filters.NumberFilter(field_name='id', lookup_expr='gte') id_max = filters.NumberFilter(field_name='id', lookup_expr='lte') state = filters.ModelMultipleChoiceFilter(field_name='state', queryset=models.SubtaskState.objects.all()) name = filters.CharFilter(field_name='task_blueprint__scheduling_unit_blueprint__name', lookup_expr='icontains') # todo: correct name? + on_sky_start_time__lt = property_filters.PropertyDateTimeFilter(field_name='on_sky_start_time', lookup_expr='lt') + on_sky_start_time__gt = property_filters.PropertyDateTimeFilter(field_name='on_sky_start_time', lookup_expr='gt') + process_start_time__lt = property_filters.PropertyDateTimeFilter(field_name='process_start_time', lookup_expr='lt') + process_stop_time__gt = property_filters.PropertyDateTimeFilter(field_name='process_start_time', lookup_expr='gt') class Meta: model = Subtask