Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for successful build prefetch #11613

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions readthedocs/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",)
Expand Down Expand Up @@ -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):
Comment on lines +926 to +927
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same feedback about not needing the first if.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted on #11616 but hasattr does indeed seem needed as hasattr() == False is what signals that prefetching is not in use and the normal method query can be run.

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"):
Expand Down
24 changes: 20 additions & 4 deletions readthedocs/projects/querysets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down