launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #15774
[Merge] lp:~stevenk/launchpad/distroseries-spec-preload into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/distroseries-spec-preload into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #681432 in Launchpad itself: "DistroSeries.valid_specifications includes OBSOLETE ones"
https://bugs.launchpad.net/launchpad/+bug/681432
Bug #1202664 in Launchpad itself: "Timeouts while fetching blueprints through the api"
https://bugs.launchpad.net/launchpad/+bug/1202664
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/distroseries-spec-preload/+merge/180046
Preload workitems as well during search_specifications. Due to the number of callsites, this will hopefully reduce specification related timeouts across the board, but we'll see.
Also due to search_specifications work, re-enable a disabled test that now works.
--
https://code.launchpad.net/~stevenk/launchpad/distroseries-spec-preload/+merge/180046
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/distroseries-spec-preload into lp:launchpad.
=== modified file 'lib/lp/blueprints/model/specification.py'
--- lib/lp/blueprints/model/specification.py 2013-06-27 15:11:38 +0000
+++ lib/lp/blueprints/model/specification.py 2013-08-14 06:58:36 +0000
@@ -335,7 +335,7 @@
else:
return "Work items for %s:" % milestone.name
- if self.work_items.count() == 0:
+ if len(self.work_items) == 0:
return ''
milestone = self.work_items[0].milestone
# Start by appending a header for the milestone of the first work
@@ -353,9 +353,9 @@
else:
assignee_part = ""
# work_items are ordered by sequence
- workitems_lines.append("%s%s: %s" % (assignee_part,
- work_item.title,
- work_item.status.name))
+ workitems_lines.append(
+ "%s%s: %s" % (
+ assignee_part, work_item.title, work_item.status.name))
return "\n".join(workitems_lines)
@property
@@ -377,9 +377,13 @@
title=title, status=status, specification=self, assignee=assignee,
milestone=milestone, sequence=sequence)
- @property
+ @cachedproperty
def work_items(self):
"""See ISpecification."""
+ return list(self._work_items)
+
+ @property
+ def _work_items(self):
return Store.of(self).find(
SpecificationWorkItem, specification=self,
deleted=False).order_by("sequence")
=== modified file 'lib/lp/blueprints/model/specificationsearch.py'
--- lib/lp/blueprints/model/specificationsearch.py 2013-06-20 05:50:00 +0000
+++ lib/lp/blueprints/model/specificationsearch.py 2013-08-14 06:58:36 +0000
@@ -36,6 +36,7 @@
)
from lp.blueprints.model.specification import Specification
from lp.blueprints.model.specificationbranch import SpecificationBranch
+from lp.blueprints.model.specificationworkitem import SpecificationWorkItem
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distroseries import IDistroSeries
from lp.registry.interfaces.person import IPersonSet
@@ -233,6 +234,12 @@
person_ids |= set(
[spec._assigneeID, spec._approverID, spec._drafterID])
get_property_cache(spec).linked_branches = []
+ get_property_cache(spec).work_items = []
+ work_items = load_referencing(
+ SpecificationWorkItem, rows, ['specification_id'])
+ for workitem in work_items:
+ person_ids.add(workitem.assignee_id)
+ get_property_cache(workitem.specification).work_items.append(workitem)
person_ids -= set([None])
list(getUtility(IPersonSet).getPrecachedPersonsFromIDs(
person_ids, need_validity=True))
=== modified file 'lib/lp/blueprints/tests/test_hasspecifications.py'
--- lib/lp/blueprints/tests/test_hasspecifications.py 2013-04-03 03:09:04 +0000
+++ lib/lp/blueprints/tests/test_hasspecifications.py 2013-08-14 06:58:36 +0000
@@ -38,17 +38,14 @@
def test_distribution_all_specifications(self):
distribution = self.factory.makeDistribution()
- self.factory.makeSpecification(
- distribution=distribution, name="spec1")
- self.factory.makeSpecification(
- distribution=distribution, name="spec2")
+ self.factory.makeSpecification(distribution=distribution, name="spec1")
+ self.factory.makeSpecification(distribution=distribution, name="spec2")
self.assertNamesOfSpecificationsAre(
["spec1", "spec2"], distribution.visible_specifications)
def test_distribution_valid_specifications(self):
distribution = self.factory.makeDistribution()
- self.factory.makeSpecification(
- distribution=distribution, name="spec1")
+ self.factory.makeSpecification(distribution=distribution, name="spec1")
self.factory.makeSpecification(
distribution=distribution, name="spec2",
status=SpecificationDefinitionStatus.OBSOLETE)
@@ -59,36 +56,26 @@
distroseries = self.factory.makeDistroSeries(name='maudlin')
distribution = distroseries.distribution
self.factory.makeSpecification(
- distribution=distribution, name="spec1",
- goal=distroseries)
- self.factory.makeSpecification(
- distribution=distribution, name="spec2",
- goal=distroseries)
- self.factory.makeSpecification(
- distribution=distribution, name="spec3")
+ distribution=distribution, name="spec1", goal=distroseries)
+ self.factory.makeSpecification(
+ distribution=distribution, name="spec2", goal=distroseries)
+ self.factory.makeSpecification(distribution=distribution, name="spec3")
self.assertNamesOfSpecificationsAre(
["spec1", "spec2"], distroseries.visible_specifications)
- # XXX: salgado, 2010-11-25, bug=681432: Test disabled because
- # DistroSeries._valid_specifications is broken.
- def disabled_test_distroseries_valid_specifications(self):
+ def test_distroseries_valid_specifications(self):
distroseries = self.factory.makeDistroSeries(name='maudlin')
distribution = distroseries.distribution
self.factory.makeSpecification(
- distribution=distribution, name="spec1",
- goal=distroseries)
- self.factory.makeSpecification(
- distribution=distribution, name="spec2",
- goal=distroseries)
- self.factory.makeSpecification(
- distribution=distribution, name="spec3",
- goal=distroseries,
+ distribution=distribution, name="spec1", goal=distroseries)
+ self.factory.makeSpecification(
+ distribution=distribution, name="spec2", goal=distroseries)
+ self.factory.makeSpecification(
+ distribution=distribution, name="spec3", goal=distroseries,
status=SpecificationDefinitionStatus.OBSOLETE)
- self.factory.makeSpecification(
- distribution=distribution, name="spec4")
+ self.factory.makeSpecification(distribution=distribution, name="spec4")
self.assertNamesOfSpecificationsAre(
- ["spec1", "spec2"],
- distroseries._valid_specifications)
+ ["spec1", "spec2"], distroseries._valid_specifications)
def test_productseries_all_specifications(self):
product = self.factory.makeProduct()
@@ -123,13 +110,11 @@
product1 = self.factory.makeProduct(project=projectgroup)
product2 = self.factory.makeProduct(project=projectgroup)
product3 = self.factory.makeProduct(project=other_projectgroup)
- self.factory.makeSpecification(
- product=product1, name="spec1")
+ self.factory.makeSpecification(product=product1, name="spec1")
self.factory.makeSpecification(
product=product2, name="spec2",
status=SpecificationDefinitionStatus.OBSOLETE)
- self.factory.makeSpecification(
- product=product3, name="spec3")
+ self.factory.makeSpecification(product=product3, name="spec3")
self.assertNamesOfSpecificationsAre(
["spec1", "spec2"], projectgroup.visible_specifications)
@@ -155,8 +140,7 @@
self.factory.makeSpecification(
product=product, name="spec2", approver=person,
status=SpecificationDefinitionStatus.OBSOLETE)
- self.factory.makeSpecification(
- product=product, name="spec3")
+ self.factory.makeSpecification(product=product, name="spec3")
self.assertNamesOfSpecificationsAre(
["spec1", "spec2"], person.visible_specifications)
@@ -168,8 +152,7 @@
self.factory.makeSpecification(
product=product, name="spec2", approver=person,
status=SpecificationDefinitionStatus.OBSOLETE)
- self.factory.makeSpecification(
- product=product, name="spec3")
+ self.factory.makeSpecification(product=product, name="spec3")
self.assertNamesOfSpecificationsAre(
["spec1"], person._valid_specifications)
@@ -181,10 +164,7 @@
def check_skipped(self, target):
"""Asserts that fields marked doNotSnapshot are skipped."""
- skipped = [
- 'all_specifications',
- 'valid_specifications',
- ]
+ skipped = ['all_specifications', 'valid_specifications']
self.assertThat(target, DoesNotSnapshot(skipped, IHasSpecifications))
def test_product(self):
=== modified file 'lib/lp/registry/tests/test_distroseries.py'
--- lib/lp/registry/tests/test_distroseries.py 2012-09-26 04:14:01 +0000
+++ lib/lp/registry/tests/test_distroseries.py 2013-08-14 06:58:36 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Tests for distroseries."""
@@ -11,6 +11,7 @@
from logging import getLogger
+from testtools.matchers import Equals
import transaction
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
@@ -19,6 +20,7 @@
from lp.registry.interfaces.distroseries import IDistroSeriesSet
from lp.registry.interfaces.pocket import PackagePublishingPocket
from lp.registry.interfaces.series import SeriesStatus
+from lp.services.database.interfaces import IStore
from lp.soyuz.enums import (
ArchivePurpose,
PackagePublishingStatus,
@@ -38,6 +40,7 @@
ANONYMOUS,
login,
person_logged_in,
+ StormStatementRecorder,
TestCase,
TestCaseWithFactory,
)
@@ -45,6 +48,7 @@
DatabaseFunctionalLayer,
LaunchpadFunctionalLayer,
)
+from lp.testing.matchers import HasQueryCount
from lp.translations.interfaces.translations import (
TranslationsBranchImportMode,
)
@@ -324,6 +328,23 @@
self.assertTrue(self.checkLegalPocket(
SeriesStatus.CURRENT, PackagePublishingPocket.UPDATES))
+ def test_valid_specifications_query_count(self):
+ distroseries = self.factory.makeDistroSeries()
+ distribution = distroseries.distribution
+ spec1 = self.factory.makeSpecification(
+ distribution=distribution, goal=distroseries)
+ spec2 = self.factory.makeSpecification(
+ distribution=distribution, goal=distroseries)
+ for i in range(5):
+ self.factory.makeSpecificationWorkItem(specification=spec1)
+ self.factory.makeSpecificationWorkItem(specification=spec2)
+ IStore(spec1.__class__).flush()
+ IStore(spec1.__class__).invalidate()
+ with StormStatementRecorder() as recorder:
+ for spec in distroseries._valid_specifications:
+ spec.workitems_text
+ self.assertThat(recorder, HasQueryCount(Equals(4)))
+
class TestDistroSeriesPackaging(TestCaseWithFactory):
=== modified file 'lib/lp/soyuz/browser/tests/test_archive_webservice.py'
--- lib/lp/soyuz/browser/tests/test_archive_webservice.py 2013-05-10 05:30:11 +0000
+++ lib/lp/soyuz/browser/tests/test_archive_webservice.py 2013-08-14 06:58:36 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
+# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__metaclass__ = type
@@ -37,14 +37,13 @@
)
from lp.testing.layers import DatabaseFunctionalLayer
from lp.testing.matchers import HasQueryCount
-from lp.testing.pages import LaunchpadWebServiceCaller
class TestArchiveWebservice(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
def setUp(self):
- TestCaseWithFactory.setUp(self)
+ super(TestArchiveWebservice, self).setUp()
with celebrity_logged_in('admin'):
self.archive = self.factory.makeArchive(
purpose=ArchivePurpose.PRIMARY)
@@ -55,9 +54,6 @@
distroseries_name = distroseries.name
person_name = person.name
- self.webservice = LaunchpadWebServiceCaller(
- 'launchpad-library', 'salgado-change-anything')
-
self.launchpad = launchpadlib_for(
"archive test", "salgado", "WRITE_PUBLIC")
self.distribution = self.launchpad.distributions[distro_name]
Follow ups