Merge lp:~edwin-grubbs/launchpad/bug-663857-product-packages-timeout-part2 into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 12252
Proposed branch: lp:~edwin-grubbs/launchpad/bug-663857-product-packages-timeout-part2
Merge into: lp:launchpad
Diff against target: 106 lines (+32/-16)
4 files modified
lib/lp/registry/browser/product.py (+9/-13)
lib/lp/registry/interfaces/product.py (+2/-0)
lib/lp/registry/model/product.py (+16/-0)
lib/lp/registry/templates/product-packages.pt (+5/-3)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-663857-product-packages-timeout-part2
Reviewer Review Type Date Requested Status
Tim Penhey (community) code Approve
Curtis Hovey (community) code Approve
Steve Kowalik (community) code* Approve
Review via email: mp+46985@code.launchpad.net

Commit message

[r=sinzui,stevenk,thumper][ui=none][bug=663857] Fixes timeout on $product/+packages page, for real.

Description of the change

Summary
-------

The $product/+packages still times out because the
ProductPackagesView.distro_packaging property would iterate over all the
product's series in order to find the product's packages.

Implementation details
----------------------

Decorated the series in series_batch so that series/packagings in the
template doesn't execute a query for storm's __nonzero__() method
repeatedly. Switched distro_packaging to use the new Product.packaging
property.
    lib/lp/registry/browser/product.py
    lib/lp/registry/interfaces/product.py
    lib/lp/registry/model/product.py

Cut in half the number of queries for the currentrelease.
    lib/lp/registry/templates/product-packages.pt

Tests
-----

./bin/test -vv -t 'xx-product-package-pages.txt|packaging-views.txt'

Demo and Q/A
------------

* Open https://qastaging.launchpad.net/obsolete-junk/+packages
  * It should not timeout.

Lint
----

Not going to fix this.

./lib/lp/registry/interfaces/product.py
     983: E301 expected 1 blank line, found 2

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

This change looks good to me, thanks!

review: Approve (code*)
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you for refactoring this code. This is good to land.

review: Approve (code)
Revision history for this message
Tim Penhey (thumper) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/registry/browser/product.py'
--- lib/lp/registry/browser/product.py 2011-01-13 20:57:45 +0000
+++ lib/lp/registry/browser/product.py 2011-01-20 21:56:36 +0000
@@ -818,6 +818,11 @@
818 # This is normal presentation.818 # This is normal presentation.
819 return ''819 return ''
820820
821 @cachedproperty
822 def packagings(self):
823 """Convert packagings to list to prevent multiple evaluations."""
824 return list(self.series.packagings)
825
821826
822class SeriesWithReleases(DecoratedSeries):827class SeriesWithReleases(DecoratedSeries):
823 """A decorated series that includes releases.828 """A decorated series that includes releases.
@@ -1119,8 +1124,9 @@
1119 @cachedproperty1124 @cachedproperty
1120 def series_batch(self):1125 def series_batch(self):
1121 """A batch of series that are active or have packages."""1126 """A batch of series that are active or have packages."""
1122 return BatchNavigator(1127 decorated_series = DecoratedResultSet(
1123 self.context.active_or_packaged_series, self.request)1128 self.context.active_or_packaged_series, DecoratedSeries)
1129 return BatchNavigator(decorated_series, self.request)
11241130
1125 @property1131 @property
1126 def distro_packaging(self):1132 def distro_packaging(self):
@@ -1132,18 +1138,8 @@
1132 title, and an attribute "packagings" which is a list of the relevant1138 title, and an attribute "packagings" which is a list of the relevant
1133 packagings for this distro and product.1139 packagings for this distro and product.
1134 """1140 """
1135 # First get a list of all relevant packagings.
1136 all_packagings = []
1137 for series in self.context.series:
1138 for packaging in series.packagings:
1139 all_packagings.append(packaging)
1140 # We sort it so that the packagings will always be displayed in the
1141 # distroseries version, then productseries name order.
1142 all_packagings.sort(key=lambda a: (a.distroseries.version,
1143 a.productseries.name, a.id))
1144
1145 distros = {}1141 distros = {}
1146 for packaging in all_packagings:1142 for packaging in self.context.packagings:
1147 distribution = packaging.distroseries.distribution1143 distribution = packaging.distroseries.distribution
1148 if distribution.name in distros:1144 if distribution.name in distros:
1149 distro = distros[distribution.name]1145 distro = distros[distribution.name]
11501146
=== modified file 'lib/lp/registry/interfaces/product.py'
--- lib/lp/registry/interfaces/product.py 2011-01-13 06:07:03 +0000
+++ lib/lp/registry/interfaces/product.py 2011-01-20 21:56:36 +0000
@@ -735,6 +735,8 @@
735 active_or_packaged_series = Attribute(735 active_or_packaged_series = Attribute(
736 _("Series that are active and/or have been packaged."))736 _("Series that are active and/or have been packaged."))
737737
738 packagings = Attribute(_("All the packagings for the project."))
739
738 def getVersionSortedSeries(statuses=None, filter_statuses=None):740 def getVersionSortedSeries(statuses=None, filter_statuses=None):
739 """Return all the series sorted by the name field as a version.741 """Return all the series sorted by the name field as a version.
740742
741743
=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py 2011-01-13 21:03:14 +0000
+++ lib/lp/registry/model/product.py 2011-01-20 21:56:36 +0000
@@ -821,6 +821,22 @@
821 return result821 return result
822822
823 @property823 @property
824 def packagings(self):
825 store = Store.of(self)
826 result = store.find(
827 (Packaging, DistroSeries),
828 Packaging.distroseries == DistroSeries.id,
829 Packaging.productseries == ProductSeries.id,
830 ProductSeries.product == self)
831 result = result.order_by(
832 DistroSeries.version, ProductSeries.name, Packaging.id)
833
834 def decorate(row):
835 packaging, distroseries = row
836 return packaging
837 return DecoratedResultSet(result, decorate)
838
839 @property
824 def name_with_project(self):840 def name_with_project(self):
825 """See lib.canonical.launchpad.interfaces.IProduct"""841 """See lib.canonical.launchpad.interfaces.IProduct"""
826 if self.project and self.project.name != self.name:842 if self.project and self.project.name != self.name:
827843
=== modified file 'lib/lp/registry/templates/product-packages.pt'
--- lib/lp/registry/templates/product-packages.pt 2011-01-14 02:47:41 +0000
+++ lib/lp/registry/templates/product-packages.pt 2011-01-20 21:56:36 +0000
@@ -136,9 +136,11 @@
136 >Apache</a>136 >Apache</a>
137 </td>137 </td>
138 <td>138 <td>
139 <span tal:condition="pkging/sourcepackage/currentrelease"139 <span
140 tal:replace="pkging/sourcepackage/currentrelease/version"140 tal:define="currentrelease pkging/sourcepackage/currentrelease"
141 >2.3.4-1</span>141 tal:condition="currentrelease"
142 tal:replace="currentrelease/version"
143 >2.3.4-1</span>
142 </td>144 </td>
143 <td>145 <td>
144 <a tal:replace="structure pkging/productseries/fmt:link" />146 <a tal:replace="structure pkging/productseries/fmt:link" />