Merge ~cjwatson/launchpad:optimize-determineFilesToSend into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 51ab588db40aad5e0ce14773a025dca8e7c75e91
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:optimize-determineFilesToSend
Merge into: launchpad:master
Diff against target: 111 lines (+57/-6)
2 files modified
lib/lp/soyuz/model/sourcepackagerelease.py (+26/-5)
lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py (+31/-1)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+450917@code.launchpad.net

Commit message

Optimize BinaryPackageBuildBehaviour.determineFilesToSend

Description of the change

This eliminates two database queries for every file that forms part of a source package. Not a lot, but this is part of buildd-manager's scan cycle so removing some unnecessary round-trips seems worthwhile.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/soyuz/model/sourcepackagerelease.py b/lib/lp/soyuz/model/sourcepackagerelease.py
2index 6edb2fe..6e1222e 100644
3--- a/lib/lp/soyuz/model/sourcepackagerelease.py
4+++ b/lib/lp/soyuz/model/sourcepackagerelease.py
5@@ -18,7 +18,7 @@ from debian.changelog import (
6 ChangelogCreateError,
7 ChangelogParseError,
8 )
9-from storm.expr import Coalesce, Join, Sum
10+from storm.expr import Coalesce, Join, LeftJoin, Sum
11 from storm.locals import DateTime, Desc, Int, Reference, Unicode
12 from storm.store import Store
13 from zope.component import getUtility
14@@ -361,11 +361,32 @@ class SourcePackageRelease(StormBase):
15 @cachedproperty
16 def files(self):
17 """See `ISourcePackageRelease`."""
18- return list(
19- Store.of(self)
20- .find(SourcePackageReleaseFile, sourcepackagerelease=self)
21+ # Preload library files, since call sites will normally need them too.
22+ return [
23+ sprf
24+ for sprf, _, _ in Store.of(self)
25+ .using(
26+ SourcePackageReleaseFile,
27+ Join(
28+ LibraryFileAlias,
29+ SourcePackageReleaseFile.libraryfile
30+ == LibraryFileAlias.id,
31+ ),
32+ LeftJoin(
33+ LibraryFileContent,
34+ LibraryFileAlias.content == LibraryFileContent.id,
35+ ),
36+ )
37+ .find(
38+ (
39+ SourcePackageReleaseFile,
40+ LibraryFileAlias,
41+ LibraryFileContent,
42+ ),
43+ SourcePackageReleaseFile.sourcepackagerelease == self,
44+ )
45 .order_by(SourcePackageReleaseFile.libraryfile_id)
46- )
47+ ]
48
49 def getFileByName(self, filename):
50 """See `ISourcePackageRelease`."""
51diff --git a/lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py b/lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py
52index ee8278e..c7eaf0d 100644
53--- a/lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py
54+++ b/lib/lp/soyuz/tests/test_binarypackagebuildbehaviour.py
55@@ -45,6 +45,7 @@ from lp.registry.interfaces.series import SeriesStatus
56 from lp.registry.interfaces.sourcepackage import SourcePackageFileType
57 from lp.services.authserver.testing import InProcessAuthServerFixture
58 from lp.services.config import config
59+from lp.services.database.sqlbase import flush_database_caches
60 from lp.services.librarian.interfaces import ILibraryFileAliasSet
61 from lp.services.log.logger import BufferLogger
62 from lp.services.macaroons.testing import MacaroonVerifies
63@@ -53,11 +54,12 @@ from lp.services.webapp import canonical_url
64 from lp.soyuz.adapters.archivedependencies import get_sources_list_for_building
65 from lp.soyuz.enums import ArchivePurpose, PackagePublishingStatus
66 from lp.soyuz.tests.soyuz import Base64KeyMatches
67-from lp.testing import TestCaseWithFactory
68+from lp.testing import StormStatementRecorder, TestCaseWithFactory
69 from lp.testing.dbuser import switch_dbuser
70 from lp.testing.gpgkeys import gpgkeysdir
71 from lp.testing.keyserver import InProcessKeyServerFixture
72 from lp.testing.layers import LaunchpadZopelessLayer, ZopelessDatabaseLayer
73+from lp.testing.matchers import HasQueryCount
74
75
76 class TestBinaryBuildPackageBehaviour(StatsMixin, TestCaseWithFactory):
77@@ -508,6 +510,34 @@ class TestBinaryBuildPackageBehaviour(StatsMixin, TestCaseWithFactory):
78 self.assertTrue(extra_args["arch_indep"])
79
80 @defer.inlineCallbacks
81+ def test_determineFilesToSend_query_count(self):
82+ build = self.factory.makeBinaryPackageBuild()
83+ behaviour = IBuildFarmJobBehaviour(build)
84+
85+ def add_file(build):
86+ build.source_package_release.addFile(
87+ self.factory.makeLibraryFileAlias(db_only=True),
88+ filetype=SourcePackageFileType.COMPONENT_ORIG_TARBALL,
89+ )
90+
91+ # This is more or less `lp.testing.record_two_runs`, but that
92+ # doesn't work with asynchronous code, and it's easy enough to
93+ # inline the relevant bits.
94+ for _ in range(2):
95+ add_file(build)
96+ flush_database_caches()
97+ with StormStatementRecorder() as recorder1:
98+ filemap = yield behaviour.determineFilesToSend()
99+ self.assertEqual(2, len(list(filemap)))
100+ for _ in range(2):
101+ add_file(build)
102+ flush_database_caches()
103+ with StormStatementRecorder() as recorder2:
104+ filemap = yield behaviour.determineFilesToSend()
105+ self.assertEqual(4, len(list(filemap)))
106+ self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
107+
108+ @defer.inlineCallbacks
109 def test_extraBuildArgs_archives_proposed(self):
110 # A build in the primary archive's proposed pocket uses the release,
111 # security, updates, and proposed pockets in the primary archive.

Subscribers

People subscribed via source and target branches

to status/vote changes: