launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #07387
[Merge] lp:~wgrant/launchpad/bug-899776 into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/bug-899776 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #899776 in Launchpad itself: "Distribution:+bugs timeout searching by component universe"
https://bugs.launchpad.net/launchpad/+bug/899776
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bug-899776/+merge/103806
This branch rewrites the package component filtering part of bugtasksearch. Old plan is https://pastebin.canonical.com/65085/, new is https://pastebin.canonical.com/65104/ -- it's about 200x faster. The full improvement is only seen with a new index that is being done in a separate branch, but it's still substantially faster without it.
I changed the SELECT to use the relatively newly denormalised SPPH.sourcepackagename, allowing rapid direct indexing into the table. It's now a normal subquery instead of a CTE, after extensive performance testing. In addition, the archive set is minimised: if we're just searching for main and universe, we don't need to search the partner archive.
--
https://code.launchpad.net/~wgrant/launchpad/bug-899776/+merge/103806
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bug-899776 into lp:launchpad.
=== modified file 'lib/lp/bugs/model/bugtasksearch.py'
--- lib/lp/bugs/model/bugtasksearch.py 2012-04-26 05:00:19 +0000
+++ lib/lp/bugs/model/bugtasksearch.py 2012-04-27 06:44:19 +0000
@@ -91,6 +91,7 @@
NULL,
)
from lp.soyuz.enums import PackagePublishingStatus
+from lp.soyuz.model.publishing import SourcePackagePublishingHistory
# This abstracts most of the columns involved in search so we can switch
@@ -737,29 +738,30 @@
"distribution or distroseries.")
if zope_isinstance(params.component, any):
- component_ids = sqlvalues(*params.component.query_values)
+ components = params.component.query_values
else:
- component_ids = sqlvalues(params.component)
-
- distro_archive_ids = [
- archive.id
- for archive in distroseries.distribution.all_distro_archives]
- with_clauses.append("""spns as (
- SELECT spr.sourcepackagename
- FROM SourcePackagePublishingHistory
- JOIN SourcePackageRelease AS spr ON spr.id =
- SourcePackagePublishingHistory.sourcepackagerelease AND
- SourcePackagePublishingHistory.distroseries = %s AND
- SourcePackagePublishingHistory.archive IN %s AND
- SourcePackagePublishingHistory.component IN %s AND
- SourcePackagePublishingHistory.status = %s
- )""" % sqlvalues(distroseries,
- distro_archive_ids,
- component_ids,
- PackagePublishingStatus.PUBLISHED))
+ components = [params.component]
+
+ # It's much faster to query for a single archive, so don't
+ # include partner unless we have to.
+ archive_ids = set(
+ distroseries.distribution.getArchiveByComponent(c.name).id
+ for c in components)
+
extra_clauses.append(
cols['BugTask.sourcepackagenameID'].is_in(
- SQL('SELECT sourcepackagename FROM spns')))
+ Select(
+ SourcePackagePublishingHistory.sourcepackagenameID,
+ tables=[SourcePackagePublishingHistory],
+ where=And(
+ SourcePackagePublishingHistory.archiveID.is_in(
+ archive_ids),
+ SourcePackagePublishingHistory.distroseries ==
+ distroseries,
+ SourcePackagePublishingHistory.componentID.is_in(
+ c.id for c in components),
+ SourcePackagePublishingHistory.status ==
+ PackagePublishingStatus.PUBLISHED))))
upstream_clause = _build_upstream_clause(params, cols)
if upstream_clause:
=== modified file 'lib/lp/bugs/tests/test_bugtask_search.py'
--- lib/lp/bugs/tests/test_bugtask_search.py 2012-04-26 04:53:53 +0000
+++ lib/lp/bugs/tests/test_bugtask_search.py 2012-04-27 06:44:19 +0000
@@ -39,6 +39,9 @@
any,
greater_than,
)
+from lp.soyuz.interfaces.archive import ArchivePurpose
+from lp.soyuz.interfaces.component import IComponentSet
+from lp.soyuz.interfaces.publishing import PackagePublishingStatus
from lp.testing import (
person_logged_in,
TestCase,
@@ -719,6 +722,48 @@
self.assertSearchFinds(params, self.bugtasks)
+class DistributionAndDistroSeriesTests:
+ """Tests which are useful for distributions and their series."""
+
+ def makeBugInComponent(self, archive, series, component):
+ pub = self.factory.makeSourcePackagePublishingHistory(
+ archive=archive, distroseries=series, component=component,
+ status=PackagePublishingStatus.PUBLISHED)
+ return self.factory.makeBugTask(
+ target=self.searchtarget.getSourcePackage(pub.sourcepackagename))
+
+ def test_search_by_component(self):
+ series = self.getCurrentSeries()
+ distro = series.distribution
+ self.factory.makeArchive(
+ distribution=distro, purpose=ArchivePurpose.PARTNER)
+
+ main = getUtility(IComponentSet)['main']
+ main_task = self.makeBugInComponent(
+ distro.main_archive, series, main)
+ universe = getUtility(IComponentSet)['universe']
+ universe_task = self.makeBugInComponent(
+ distro.main_archive, series, universe)
+ partner = getUtility(IComponentSet)['partner']
+ partner_task = self.makeBugInComponent(
+ distro.getArchiveByComponent('partner'), series, partner)
+
+ # Searches for a single component work.
+ params = self.getBugTaskSearchParams(user=None, component=main)
+ self.assertSearchFinds(params, [main_task])
+ params = self.getBugTaskSearchParams(user=None, component=universe)
+ self.assertSearchFinds(params, [universe_task])
+
+ # Non-primary-archive component searches also work.
+ params = self.getBugTaskSearchParams(user=None, component=partner)
+ self.assertSearchFinds(params, [partner_task])
+
+ # A combination of archives works.
+ params = self.getBugTaskSearchParams(
+ user=None, component=any(partner, main))
+ self.assertSearchFinds(params, [main_task, partner_task])
+
+
class BugTargetTestBase:
"""A base class for the bug target mixin classes.
@@ -1062,7 +1107,8 @@
class DistributionTarget(BugTargetTestBase, ProductAndDistributionTests,
BugTargetWithBugSuperVisor,
- ProjectGroupAndDistributionTests):
+ ProjectGroupAndDistributionTests,
+ DistributionAndDistroSeriesTests):
"""Use a distribution as the bug target."""
def setUp(self):
@@ -1087,6 +1133,11 @@
"""See `ProductAndDistributionTests`."""
return self.factory.makeDistroSeries(distribution=self.searchtarget)
+ def getCurrentSeries(self):
+ if self.searchtarget.currentseries is None:
+ self.makeSeries()
+ return self.searchtarget.currentseries
+
def setUpStructuralSubscriptions(self):
# See `ProjectGroupAndDistributionTests`.
subscriber = self.factory.makePerson()
@@ -1110,7 +1161,8 @@
return self.bugtasks[1:] + self.bugtasks[:1]
-class DistroseriesTarget(BugTargetTestBase, ProjectGroupAndDistributionTests):
+class DistroseriesTarget(BugTargetTestBase, ProjectGroupAndDistributionTests,
+ DistributionAndDistroSeriesTests):
"""Use a distro series as the bug target."""
def setUp(self):
@@ -1132,6 +1184,9 @@
def setBugParamsTarget(self, params, target):
params.setDistroSeries(target)
+ def getCurrentSeries(self):
+ return self.searchtarget
+
def setUpMilestoneSorting(self):
with person_logged_in(self.owner):
milestone_1 = self.factory.makeMilestone(
Follow ups