From e4a7a5a23d41eff5d3db295895ff4732c5523614 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Wed, 19 Oct 2022 16:34:39 -0300 Subject: [PATCH 1/3] Rework schedule escalation chains/policies count as a subquery --- engine/apps/api/serializers/schedule_base.py | 3 ++- engine/apps/api/views/schedule.py | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/engine/apps/api/serializers/schedule_base.py b/engine/apps/api/serializers/schedule_base.py index b3e1858d..05fc126c 100644 --- a/engine/apps/api/serializers/schedule_base.py +++ b/engine/apps/api/serializers/schedule_base.py @@ -76,7 +76,8 @@ class ScheduleBaseSerializer(EagerLoadingMixin, serializers.ModelSerializer): def get_number_of_escalation_chains(self, obj): # num_escalation_chains param added in queryset via annotate. Check ScheduleView.get_queryset # return 0 for just created schedules - return getattr(obj, "num_escalation_chains", 0) + num = getattr(obj, "num_escalation_chains", 0) + return num if num is not None else 0 def validate(self, attrs): if "slack_channel_id" in attrs: diff --git a/engine/apps/api/views/schedule.py b/engine/apps/api/views/schedule.py index 4bc5764e..d0af3d0b 100644 --- a/engine/apps/api/views/schedule.py +++ b/engine/apps/api/views/schedule.py @@ -13,7 +13,7 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.views import Response from rest_framework.viewsets import ModelViewSet -from apps.alerts.models import EscalationChain +from apps.alerts.models import EscalationChain, EscalationPolicy from apps.api.permissions import MODIFY_ACTIONS, READ_ACTIONS, ActionPermission, AnyRole, IsAdmin, IsAdminOrEditor from apps.api.serializers.schedule_base import ScheduleFastSerializer from apps.api.serializers.schedule_polymorphic import ( @@ -108,13 +108,16 @@ class ScheduleView( slack_team_identity=organization.slack_team_identity, slack_id=OuterRef("channel"), ) + escalation_policies = ( + EscalationPolicy.objects.values("notify_schedule") + .order_by("notify_schedule") + .annotate(num_escalation_chains=Count("notify_schedule")) + .filter(notify_schedule=OuterRef("id")) + ) queryset = queryset.annotate( slack_channel_name=Subquery(slack_channels.values("name")[:1]), slack_channel_pk=Subquery(slack_channels.values("public_primary_key")[:1]), - num_escalation_chains=Count( - "escalation_policies__escalation_chain", - distinct=True, - ), + num_escalation_chains=Subquery(escalation_policies.values("num_escalation_chains")[:1]), ) return queryset From 3d171f20f78b94309c180f50b975dee33e340599 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Wed, 19 Oct 2022 17:03:09 -0300 Subject: [PATCH 2/3] Defer large unused queryset fields when listing schedules --- engine/apps/api/views/schedule.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/engine/apps/api/views/schedule.py b/engine/apps/api/views/schedule.py index d0af3d0b..9c52a69c 100644 --- a/engine/apps/api/views/schedule.py +++ b/engine/apps/api/views/schedule.py @@ -124,9 +124,12 @@ class ScheduleView( def get_queryset(self): is_short_request = self.request.query_params.get("short", "false") == "true" organization = self.request.auth.organization - queryset = OnCallSchedule.objects.filter( - organization=organization, - team=self.request.user.current_team, + queryset = OnCallSchedule.objects.filter(organization=organization, team=self.request.user.current_team).defer( + # avoid requesting large text fields which are not used when listing schedules + "cached_ical_file_primary", + "prev_ical_file_primary", + "cached_ical_file_overrides", + "prev_ical_file_overrides", ) if not is_short_request: queryset = self._annotate_queryset(queryset) From 64397529495314d9199da7cb74c59d44d1673c57 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Thu, 20 Oct 2022 12:57:59 -0300 Subject: [PATCH 3/3] Rewrite fallback condition for num escalation chains Co-authored-by: Vadim Stepanov --- engine/apps/api/serializers/schedule_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/apps/api/serializers/schedule_base.py b/engine/apps/api/serializers/schedule_base.py index 05fc126c..c2eb6ea6 100644 --- a/engine/apps/api/serializers/schedule_base.py +++ b/engine/apps/api/serializers/schedule_base.py @@ -77,7 +77,7 @@ class ScheduleBaseSerializer(EagerLoadingMixin, serializers.ModelSerializer): # num_escalation_chains param added in queryset via annotate. Check ScheduleView.get_queryset # return 0 for just created schedules num = getattr(obj, "num_escalation_chains", 0) - return num if num is not None else 0 + return num or 0 def validate(self, attrs): if "slack_channel_id" in attrs: