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
1=== modified file 'lib/lp/registry/browser/product.py'
2--- lib/lp/registry/browser/product.py 2011-01-13 20:57:45 +0000
3+++ lib/lp/registry/browser/product.py 2011-01-20 21:56:36 +0000
4@@ -818,6 +818,11 @@
5 # This is normal presentation.
6 return ''
7
8+ @cachedproperty
9+ def packagings(self):
10+ """Convert packagings to list to prevent multiple evaluations."""
11+ return list(self.series.packagings)
12+
13
14 class SeriesWithReleases(DecoratedSeries):
15 """A decorated series that includes releases.
16@@ -1119,8 +1124,9 @@
17 @cachedproperty
18 def series_batch(self):
19 """A batch of series that are active or have packages."""
20- return BatchNavigator(
21- self.context.active_or_packaged_series, self.request)
22+ decorated_series = DecoratedResultSet(
23+ self.context.active_or_packaged_series, DecoratedSeries)
24+ return BatchNavigator(decorated_series, self.request)
25
26 @property
27 def distro_packaging(self):
28@@ -1132,18 +1138,8 @@
29 title, and an attribute "packagings" which is a list of the relevant
30 packagings for this distro and product.
31 """
32- # First get a list of all relevant packagings.
33- all_packagings = []
34- for series in self.context.series:
35- for packaging in series.packagings:
36- all_packagings.append(packaging)
37- # We sort it so that the packagings will always be displayed in the
38- # distroseries version, then productseries name order.
39- all_packagings.sort(key=lambda a: (a.distroseries.version,
40- a.productseries.name, a.id))
41-
42 distros = {}
43- for packaging in all_packagings:
44+ for packaging in self.context.packagings:
45 distribution = packaging.distroseries.distribution
46 if distribution.name in distros:
47 distro = distros[distribution.name]
48
49=== modified file 'lib/lp/registry/interfaces/product.py'
50--- lib/lp/registry/interfaces/product.py 2011-01-13 06:07:03 +0000
51+++ lib/lp/registry/interfaces/product.py 2011-01-20 21:56:36 +0000
52@@ -735,6 +735,8 @@
53 active_or_packaged_series = Attribute(
54 _("Series that are active and/or have been packaged."))
55
56+ packagings = Attribute(_("All the packagings for the project."))
57+
58 def getVersionSortedSeries(statuses=None, filter_statuses=None):
59 """Return all the series sorted by the name field as a version.
60
61
62=== modified file 'lib/lp/registry/model/product.py'
63--- lib/lp/registry/model/product.py 2011-01-13 21:03:14 +0000
64+++ lib/lp/registry/model/product.py 2011-01-20 21:56:36 +0000
65@@ -821,6 +821,22 @@
66 return result
67
68 @property
69+ def packagings(self):
70+ store = Store.of(self)
71+ result = store.find(
72+ (Packaging, DistroSeries),
73+ Packaging.distroseries == DistroSeries.id,
74+ Packaging.productseries == ProductSeries.id,
75+ ProductSeries.product == self)
76+ result = result.order_by(
77+ DistroSeries.version, ProductSeries.name, Packaging.id)
78+
79+ def decorate(row):
80+ packaging, distroseries = row
81+ return packaging
82+ return DecoratedResultSet(result, decorate)
83+
84+ @property
85 def name_with_project(self):
86 """See lib.canonical.launchpad.interfaces.IProduct"""
87 if self.project and self.project.name != self.name:
88
89=== modified file 'lib/lp/registry/templates/product-packages.pt'
90--- lib/lp/registry/templates/product-packages.pt 2011-01-14 02:47:41 +0000
91+++ lib/lp/registry/templates/product-packages.pt 2011-01-20 21:56:36 +0000
92@@ -136,9 +136,11 @@
93 >Apache</a>
94 </td>
95 <td>
96- <span tal:condition="pkging/sourcepackage/currentrelease"
97- tal:replace="pkging/sourcepackage/currentrelease/version"
98- >2.3.4-1</span>
99+ <span
100+ tal:define="currentrelease pkging/sourcepackage/currentrelease"
101+ tal:condition="currentrelease"
102+ tal:replace="currentrelease/version"
103+ >2.3.4-1</span>
104 </td>
105 <td>
106 <a tal:replace="structure pkging/productseries/fmt:link" />