Merge lp:~adeuring/launchpad/bug-739065-2 into lp:launchpad

Proposed by Abel Deuring
Status: Merged
Approved by: Brad Crittenden
Approved revision: no longer in the source branch.
Merged at revision: 13098
Proposed branch: lp:~adeuring/launchpad/bug-739065-2
Merge into: lp:launchpad
Prerequisite: lp:~adeuring/launchpad/bug-739065
Diff against target: 210 lines (+144/-26)
2 files modified
lib/lp/soyuz/model/distroseriessourcepackagerelease.py (+51/-26)
lib/lp/soyuz/tests/test_distroseriessourcepackagerelease.py (+93/-0)
To merge this branch: bzr merge lp:~adeuring/launchpad/bug-739065-2
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+61768@code.launchpad.net

Commit message

[r=bac][bug=739065] pre-join BinaryPackageName in the SQL query in DistroSeriesSourcePackageRelease.binaries; pre-join DistroSeriesPackageCache in the SQL query in DistributionSourcePackageRelease.sample_binary_packages

Description of the change

This branch is a second step to fix bug 739065: SourcePackage:+index timeouts.

The OOPS reports mentioned in the bug report show that two queries are repeated very often. The repetition of one of these queries is removed in the prerequiste branch ~adeuring/launchpad/bug-739065. This branch removes the other repetition.

I added some _very_ basic units for the affected property, DistroSeriesSourcePackageRelease.binaries, and I replaced the ancient SQLObject query with a Storm query.

test: ./bin/test soyuz -vvt test_distroseriessourcepackagerelease

no lint

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

Abel this branch looks good. On IRC we discussed not forcing the use of the main store. Other than that it looks great. Thanks for the nice branch.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/soyuz/model/distroseriessourcepackagerelease.py'
--- lib/lp/soyuz/model/distroseriessourcepackagerelease.py 2011-04-18 12:53:54 +0000
+++ lib/lp/soyuz/model/distroseriessourcepackagerelease.py 2011-05-20 14:16:58 +0000
@@ -12,18 +12,33 @@
12 ]12 ]
1313
14from lazr.delegates import delegates14from lazr.delegates import delegates
15from operator import itemgetter
16from storm.expr import (
17 And,
18 Desc,
19 Join,
20 )
21from storm.store import Store
15from zope.interface import implements22from zope.interface import implements
16from zope.security.proxy import removeSecurityProxy23from zope.security.proxy import removeSecurityProxy
1724
18from canonical.database.sqlbase import sqlvalues25from canonical.database.sqlbase import sqlvalues
26from canonical.launchpad.components.decoratedresultset import (
27 DecoratedResultSet,
28 )
19from lp.registry.interfaces.distroseries import IDistroSeries29from lp.registry.interfaces.distroseries import IDistroSeries
20from lp.soyuz.enums import PackagePublishingStatus30from lp.soyuz.enums import PackagePublishingStatus
21from lp.soyuz.interfaces.distroseriessourcepackagerelease import (31from lp.soyuz.interfaces.distroseriessourcepackagerelease import (
22 IDistroSeriesSourcePackageRelease,32 IDistroSeriesSourcePackageRelease,
23 )33 )
24from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease34from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease
35from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
36from lp.soyuz.model.binarypackagename import BinaryPackageName
25from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease37from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
26from lp.soyuz.model.publishing import SourcePackagePublishingHistory38from lp.soyuz.model.publishing import (
39 BinaryPackagePublishingHistory,
40 SourcePackagePublishingHistory,
41 )
2742
2843
29class DistroSeriesSourcePackageRelease:44class DistroSeriesSourcePackageRelease:
@@ -112,7 +127,7 @@
112127
113 return (128 return (
114 [build for build in distro_builds129 [build for build in distro_builds
115 if build.distro_arch_series.distroseries == self.distroseries])130 if build.distro_arch_series.distroseries == self.distroseries])
116131
117 @property132 @property
118 def files(self):133 def files(self):
@@ -122,30 +137,40 @@
122 @property137 @property
123 def binaries(self):138 def binaries(self):
124 """See `IDistroSeriesSourcePackageRelease`."""139 """See `IDistroSeriesSourcePackageRelease`."""
125 clauseTables = [140 # Avoid circular imports.
126 'BinaryPackageRelease',141 from lp.soyuz.model.distroarchseries import DistroArchSeries
127 'DistroArchSeries',142 store = Store.of(self.distroseries)
128 'BinaryPackageBuild',143 result_row = (
129 'BinaryPackagePublishingHistory'144 BinaryPackageRelease, BinaryPackageBuild, BinaryPackageName)
130 ]145
131146 tables = (
132 query = """147 BinaryPackageRelease,
133 BinaryPackageRelease.build=BinaryPackageBuild.id AND148 Join(
134 DistroArchSeries.id =149 BinaryPackageBuild,
135 BinaryPackagePublishingHistory.distroarchseries AND150 BinaryPackageBuild.id == BinaryPackageRelease.buildID),
136 BinaryPackagePublishingHistory.binarypackagerelease=151 Join(
137 BinaryPackageRelease.id AND152 BinaryPackagePublishingHistory,
138 DistroArchSeries.distroseries=%s AND153 BinaryPackageRelease.id ==
139 BinaryPackagePublishingHistory.archive IN %s AND154 BinaryPackagePublishingHistory.binarypackagereleaseID),
140 BinaryPackageBuild.source_package_release=%s155 Join(
141 """ % sqlvalues(self.distroseries,156 DistroArchSeries,
142 self.distroseries.distribution.all_distro_archive_ids,157 DistroArchSeries.id ==
143 self.sourcepackagerelease)158 BinaryPackagePublishingHistory.distroarchseriesID),
144159 Join(
145 return BinaryPackageRelease.select(160 BinaryPackageName,
146 query, prejoinClauseTables=['BinaryPackageBuild'],161 BinaryPackageName.id ==
147 orderBy=['-id'], clauseTables=clauseTables,162 BinaryPackageRelease.binarypackagenameID))
148 distinct=True)163 archive_ids = list(
164 self.distroseries.distribution.all_distro_archive_ids)
165 binaries = store.using(*tables).find(
166 result_row,
167 And(
168 DistroArchSeries.distroseriesID == self.distroseries.id,
169 BinaryPackagePublishingHistory.archiveID.is_in(archive_ids),
170 BinaryPackageBuild.source_package_release ==
171 self.sourcepackagerelease))
172 binaries.order_by(Desc(BinaryPackageRelease.id)).config(distinct=True)
173 return DecoratedResultSet(binaries, itemgetter(0))
149174
150 @property175 @property
151 def changesfile(self):176 def changesfile(self):
152177
=== added file 'lib/lp/soyuz/tests/test_distroseriessourcepackagerelease.py'
--- lib/lp/soyuz/tests/test_distroseriessourcepackagerelease.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/tests/test_distroseriessourcepackagerelease.py 2011-05-20 14:16:58 +0000
@@ -0,0 +1,93 @@
1# Copyright 2011 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Tests for DistroSeriesSourcePackageRelease."""
5
6from storm.store import Store
7from testtools.matchers import Equals
8
9from canonical.testing.layers import DatabaseFunctionalLayer
10from lp.soyuz.enums import PackagePublishingStatus
11from lp.soyuz.model.distroseriessourcepackagerelease import (
12 DistroSeriesSourcePackageRelease,
13 )
14from lp.testing import (
15 StormStatementRecorder,
16 TestCaseWithFactory,
17 )
18from lp.testing.matchers import HasQueryCount
19
20
21class TestDistroSeriesSourcePackageRelease(TestCaseWithFactory):
22 """Tests for DistroSeriesSourcePackageRelease."""
23
24 layer = DatabaseFunctionalLayer
25
26 def setUp(self):
27 super(TestDistroSeriesSourcePackageRelease, self).setUp()
28 self.sourcepackagerelease = self.factory.makeSourcePackageRelease()
29 self.distroarchseries = self.factory.makeDistroArchSeries(
30 distroseries=self.sourcepackagerelease.sourcepackage.distroseries)
31 self.dssp_release = DistroSeriesSourcePackageRelease(
32 self.distroarchseries.distroseries, self.sourcepackagerelease)
33
34 def makeBinaryPackageRelease(self, name=None):
35 if name is None:
36 name = self.factory.makeBinaryPackageName()
37 bp_build = self.factory.makeBinaryPackageBuild(
38 source_package_release=self.sourcepackagerelease,
39 distroarchseries=self.distroarchseries)
40 bp_release = self.factory.makeBinaryPackageRelease(
41 build=bp_build, binarypackagename=name)
42 sourcepackagename = self.sourcepackagerelease.sourcepackagename
43 self.factory.makeSourcePackagePublishingHistory(
44 sourcepackagename,
45 sourcepackagerelease=self.sourcepackagerelease,
46 distroseries=self.sourcepackagerelease.sourcepackage.distroseries,
47 status=PackagePublishingStatus.PUBLISHED)
48 self.factory.makeBinaryPackagePublishingHistory(
49 binarypackagerelease=bp_release,
50 distroarchseries=self.distroarchseries)
51 return bp_release
52
53 def test_binaries__no_releases(self):
54 # If no binary releases exist,
55 # DistroSeriesSourcePackageRelease.binaries returns an empty
56 # sequence.
57 self.assertEqual(0, self.dssp_release.binaries.count())
58
59 def test_binaries__one_release_for_source_package(self):
60 # If a binary release exists, it is returned by
61 # DistroSeriesSourcePackageRelease.binaries.
62 bp_release = self.makeBinaryPackageRelease()
63 self.assertEqual(
64 [bp_release], list(self.dssp_release.binaries))
65
66 def test_binaries__two_releases_for_source_package(self):
67 # If two binary releases with the sam name exist, both
68 # are returned. The more recent one is returned first.
69 name = self.factory.makeBinaryPackageName()
70 bp_release_one = self.makeBinaryPackageRelease(name)
71 bp_release_two = self.makeBinaryPackageRelease(name)
72 self.assertEqual(
73 [bp_release_two, bp_release_one],
74 list(self.dssp_release.binaries))
75
76 def test_prejoins(self):
77 # The properties BinaryPackageRelease.build and
78 # and BinaryPackageRelease.binarypackagename of the
79 # the result objects are preloaded in the query
80 # issued in DistroSeriesSourcePackageRelease.binaries.
81 self.makeBinaryPackageRelease()
82 # Both properties we want to check have been created
83 # in makeBinaryPackageRelease() and are thus already
84 # in Storm's cache. We must empty the cache, otherwise
85 # accessing bp_release.build and
86 # bp_release.binarypackagename will never cause an
87 # SQL query to be issued.
88 Store.of(self.distroarchseries).invalidate()
89 [bp_release] = list(self.dssp_release.binaries)
90 with StormStatementRecorder() as recorder:
91 bp_release.build
92 bp_release.binarypackagename
93 self.assertThat(recorder, HasQueryCount(Equals(0)))