From a6e1fdefcc874f5b0f69f0baa770f556eeb376b1 Mon Sep 17 00:00:00 2001 From: Anthony Date: Wed, 25 Sep 2024 03:26:00 -0700 Subject: [PATCH] Add support for successful build prefetch (#11613) We use both latest build and latest successful build in the project listing template. --- readthedocs/projects/models.py | 8 ++++++++ readthedocs/projects/querysets.py | 24 ++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index b3f9a9b9aba..f09e98673a3 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -575,6 +575,7 @@ class Project(models.Model): # Property used for storing the latest build for a project when prefetching LATEST_BUILD_CACHE = "_latest_build" + LATEST_SUCCESSFUL_BUILD_CACHE = "_latest_successful_build" class Meta: ordering = ("slug",) @@ -920,6 +921,13 @@ def conf_dir(self, version=LATEST): @property def has_good_build(self): + # Check if there is `_latest_successful_build` attribute in the Queryset. + # Used for database optimization. + if hasattr(self, self.LATEST_SUCCESSFUL_BUILD_CACHE): + if build_successful := getattr(self, self.LATEST_SUCCESSFUL_BUILD_CACHE): + return build_successful[0] + return None + # Check if there is `_good_build` annotation in the Queryset. # Used for Database optimization. if hasattr(self, "_good_build"): diff --git a/readthedocs/projects/querysets.py b/readthedocs/projects/querysets.py index 5725af100e1..baa17db7e76 100644 --- a/readthedocs/projects/querysets.py +++ b/readthedocs/projects/querysets.py @@ -132,17 +132,33 @@ def prefetch_latest_build(self): from readthedocs.builds.models import Build # Prefetch the latest build for each project. - subquery = Subquery( + subquery_build_latest = Subquery( Build.internal.filter(project=OuterRef("project_id")) .order_by("-date") .values_list("id", flat=True)[:1] ) - latest_build = Prefetch( + prefetch_build_latest = Prefetch( "builds", - Build.internal.filter(pk__in=subquery), + Build.internal.filter(pk__in=subquery_build_latest), to_attr=self.model.LATEST_BUILD_CACHE, ) - return self.prefetch_related(latest_build) + + # Prefetch the latest successful build for each project. + subquery_build_successful = Subquery( + Build.internal.filter(project=OuterRef("project_id")) + .order_by("-date") + .values_list("id", flat=True)[:1] + ) + prefetch_build_successful = Prefetch( + "builds", + Build.internal.filter(pk__in=subquery_build_successful), + to_attr=self.model.LATEST_SUCCESSFUL_BUILD_CACHE, + ) + + return self.prefetch_related( + prefetch_build_latest, + prefetch_build_successful, + ) # Aliases