Merge lp:~edwin-grubbs/launchpad/bug-668047-project-dsp-portlet-timeout into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Approved by: Robert Collins
Approved revision: no longer in the source branch.
Merged at revision: 11920
Proposed branch: lp:~edwin-grubbs/launchpad/bug-668047-project-dsp-portlet-timeout
Merge into: lp:launchpad
Diff against target: 213 lines (+45/-38)
5 files modified
lib/lp/registry/browser/tests/product-portlet-packages-view.txt (+3/-3)
lib/lp/registry/doc/distribution.txt (+19/-15)
lib/lp/registry/model/distribution.py (+14/-12)
lib/lp/registry/stories/webservice/xx-distribution.txt (+7/-6)
lib/lp/soyuz/browser/tests/distribution-views.txt (+2/-2)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-668047-project-dsp-portlet-timeout
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
Review via email: mp+39917@code.launchpad.net

Commit message

Fix timeout finding suggested ubuntu packages to link to a project.

Description of the change

Summary
-------

The project page would timeout when the "Packages in Ubuntu" portlet
would find a huge number of packages matching the project's name that
could be suggested for linking. The subquery for checking the
SourcePackageRelease and SourcePackagePublishingHistory table forced
postgres to use a nested loop, which was very inefficent.

Switching to using a join made it about 200 times faster. Because there
can be multiple SPPH records per DSP, the SELECT had to be made
DISTINCT. The DISTINCT caused some of the tests to break because the
order of the results was nondeterministic when the rank is NULL (i.e.
when a DSP is matched with LIKE as opposed to with the fti). I added the
DSP.name to the ORDER BY clause to make the tests less fragile.

Tests
-----

./bin/test -vv -t 'doc/distribution.txt|xx-distribution.txt'

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

* Open https://qastaging.launchpad.net/do
  * It should not timeout.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

Nice.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/registry/browser/tests/product-portlet-packages-view.txt'
--- lib/lp/registry/browser/tests/product-portlet-packages-view.txt 2010-10-19 18:44:31 +0000
+++ lib/lp/registry/browser/tests/product-portlet-packages-view.txt 2010-11-12 16:05:06 +0000
@@ -179,8 +179,8 @@
179 ... principal=product.owner)179 ... principal=product.owner)
180 >>> for dsp in view.suggestions:180 >>> for dsp in view.suggestions:
181 ... print dsp.name181 ... print dsp.name
182 ba-bingo
182 bingo183 bingo
183 ba-bingo
184184
185 >>> content = find_tag_by_id(view.render(), 'portlet-packages')185 >>> content = find_tag_by_id(view.render(), 'portlet-packages')
186 >>> print extract_text(content)186 >>> print extract_text(content)
@@ -191,8 +191,8 @@
191 let distribution and upstream maintainers share bugs, patches, and191 let distribution and upstream maintainers share bugs, patches, and
192 translations efficiently.192 translations efficiently.
193 Ubuntu Hoary packages:193 Ubuntu Hoary packages:
194 bingo194 ba-bingo
195 ba-bingo...195 bingo...
196196
197But the limit is 8 packages.197But the limit is 8 packages.
198198
199199
=== modified file 'lib/lp/registry/doc/distribution.txt'
--- lib/lp/registry/doc/distribution.txt 2010-11-02 05:48:54 +0000
+++ lib/lp/registry/doc/distribution.txt 2010-11-12 16:05:06 +0000
@@ -172,8 +172,11 @@
172a certain string through the magic of fti. For instance:172a certain string through the magic of fti. For instance:
173173
174 >>> packages = ubuntu.searchSourcePackageCaches("mozilla")174 >>> packages = ubuntu.searchSourcePackageCaches("mozilla")
175 >>> print packages.count()175 >>> for distro_source_package_cache, source_name, rank in packages:
176 1176 ... print "%-17s rank:%s" % (
177 ... distro_source_package_cache.name,
178 ... type(rank))
179 mozilla-firefox rank:<type 'float'>
177180
178The search also matches on exact package names which fti doesn't like,181The search also matches on exact package names which fti doesn't like,
179and even on substrings:182and even on substrings:
@@ -183,14 +186,15 @@
183 1186 1
184 >>> packages = ubuntu.searchSourcePackageCaches('a')187 >>> packages = ubuntu.searchSourcePackageCaches('a')
185 >>> for distro_source_package_cache, source_name, rank in packages:188 >>> for distro_source_package_cache, source_name, rank in packages:
186 ... print "%s: %s" % (189 ... print "%s: %-17s rank:%s" % (
187 ... distro_source_package_cache.__class__.__name__,190 ... distro_source_package_cache.__class__.__name__,
188 ... distro_source_package_cache.name)191 ... distro_source_package_cache.name,
189 DistributionSourcePackageCache: mozilla-firefox192 ... type(rank))
190 DistributionSourcePackageCache: netapplet193 DistributionSourcePackageCache: alsa-utils rank:<type 'NoneType'>
191 DistributionSourcePackageCache: alsa-utils194 DistributionSourcePackageCache: commercialpackage rank:<type 'NoneType'>
192 DistributionSourcePackageCache: foobar195 DistributionSourcePackageCache: foobar rank:<type 'NoneType'>
193 DistributionSourcePackageCache: commercialpackage196 DistributionSourcePackageCache: mozilla-firefox rank:<type 'NoneType'>
197 DistributionSourcePackageCache: netapplet rank:<type 'NoneType'>
194198
195The searchSourcePackages() method just returns a decorated version199The searchSourcePackages() method just returns a decorated version
196of the results from searchSourcePackageCaches():200of the results from searchSourcePackageCaches():
@@ -198,11 +202,11 @@
198 >>> packages = ubuntu.searchSourcePackages('a')202 >>> packages = ubuntu.searchSourcePackages('a')
199 >>> for dsp in packages:203 >>> for dsp in packages:
200 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)204 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)
205 DistributionSourcePackage: alsa-utils
206 DistributionSourcePackage: commercialpackage
207 DistributionSourcePackage: foobar
201 DistributionSourcePackage: mozilla-firefox208 DistributionSourcePackage: mozilla-firefox
202 DistributionSourcePackage: netapplet209 DistributionSourcePackage: netapplet
203 DistributionSourcePackage: alsa-utils
204 DistributionSourcePackage: foobar
205 DistributionSourcePackage: commercialpackage
206210
207searchSourcePackages() also has a has_packaging parameter that211searchSourcePackages() also has a has_packaging parameter that
208it just passes on to searchSourcePackageCaches(), and it restricts212it just passes on to searchSourcePackageCaches(), and it restricts
@@ -212,14 +216,14 @@
212 >>> packages = ubuntu.searchSourcePackages('a', has_packaging=True)216 >>> packages = ubuntu.searchSourcePackages('a', has_packaging=True)
213 >>> for dsp in packages:217 >>> for dsp in packages:
214 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)218 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)
219 DistributionSourcePackage: alsa-utils
215 DistributionSourcePackage: mozilla-firefox220 DistributionSourcePackage: mozilla-firefox
216 DistributionSourcePackage: netapplet221 DistributionSourcePackage: netapplet
217 DistributionSourcePackage: alsa-utils
218 >>> packages = ubuntu.searchSourcePackages('a', has_packaging=False)222 >>> packages = ubuntu.searchSourcePackages('a', has_packaging=False)
219 >>> for dsp in packages:223 >>> for dsp in packages:
220 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)224 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)
225 DistributionSourcePackage: commercialpackage
221 DistributionSourcePackage: foobar226 DistributionSourcePackage: foobar
222 DistributionSourcePackage: commercialpackage
223227
224searchSourcePackages() also has a publishing_distroseries parameter that228searchSourcePackages() also has a publishing_distroseries parameter that
225it just passes on to searchSourcePackageCaches(), and it restricts the229it just passes on to searchSourcePackageCaches(), and it restricts the
@@ -230,8 +234,8 @@
230 ... 'a', publishing_distroseries=ubuntu.currentseries)234 ... 'a', publishing_distroseries=ubuntu.currentseries)
231 >>> for dsp in packages:235 >>> for dsp in packages:
232 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)236 ... print "%s: %s" % (dsp.__class__.__name__, dsp.name)
237 DistributionSourcePackage: alsa-utils
233 DistributionSourcePackage: netapplet238 DistributionSourcePackage: netapplet
234 DistributionSourcePackage: alsa-utils
235239
236240
237Searching for binary packages241Searching for binary packages
238242
=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py 2010-11-05 14:56:34 +0000
+++ lib/lp/registry/model/distribution.py 2010-11-12 16:05:06 +0000
@@ -1142,16 +1142,17 @@
11421142
1143 publishing_condition = ''1143 publishing_condition = ''
1144 if publishing_distroseries is not None:1144 if publishing_distroseries is not None:
1145 publishing_condition = """1145 origin += [
1146 AND EXISTS (1146 Join(SourcePackageRelease,
1147 SELECT 11147 SourcePackageRelease.sourcepackagename ==
1148 FROM SourcePackageRelease spr1148 SourcePackageName.id),
1149 JOIN SourcePackagePublishingHistory spph1149 Join(SourcePackagePublishingHistory,
1150 ON spph.sourcepackagerelease = spr.id1150 SourcePackagePublishingHistory.sourcepackagerelease ==
1151 WHERE spr.sourcepackagename = SourcePackageName.id1151 SourcePackageRelease.id),
1152 AND spph.distroseries = %d1152 ]
1153 )""" % (1153 publishing_condition = (
1154 publishing_distroseries.id)1154 "AND SourcePackagePublishingHistory.distroseries = %d"
1155 % publishing_distroseries.id)
11551156
1156 packaging_query = """1157 packaging_query = """
1157 SELECT 11158 SELECT 1
@@ -1178,8 +1179,9 @@
1178 quote(text), quote_like(text), has_packaging_condition,1179 quote(text), quote_like(text), has_packaging_condition,
1179 publishing_condition)1180 publishing_condition)
1180 dsp_caches_with_ranks = store.using(*origin).find(1181 dsp_caches_with_ranks = store.using(*origin).find(
1181 find_spec, condition).order_by('rank DESC')1182 find_spec, condition).order_by(
11821183 'rank DESC, DistributionSourcePackageCache.name')
1184 dsp_caches_with_ranks.config(distinct=True)
1183 return dsp_caches_with_ranks1185 return dsp_caches_with_ranks
11841186
1185 def searchSourcePackages(1187 def searchSourcePackages(
11861188
=== modified file 'lib/lp/registry/stories/webservice/xx-distribution.txt'
--- lib/lp/registry/stories/webservice/xx-distribution.txt 2010-10-18 22:24:59 +0000
+++ lib/lp/registry/stories/webservice/xx-distribution.txt 2010-11-12 16:05:06 +0000
@@ -1,4 +1,5 @@
1= Distributions =1Distributions
2=============
23
3At the top level we provide the collection of all distributions, with4At the top level we provide the collection of all distributions, with
4Ubuntu and its flavours being the first on the list.5Ubuntu and its flavours being the first on the list.
@@ -50,7 +51,8 @@
50 title: u'Ubuntu Linux'51 title: u'Ubuntu Linux'
5152
5253
53== Distribution Custom Operations ==54Distribution Custom Operations
55==============================
5456
55Distribution has some custom operations.57Distribution has some custom operations.
5658
@@ -113,11 +115,11 @@
113115
114 >>> for entry in alsa_results['entries']:116 >>> for entry in alsa_results['entries']:
115 ... print entry['self_link']117 ... print entry['self_link']
118 http://.../ubuntu/+source/alsa-utils
119 http://.../ubuntu/+source/commercialpackage
120 http://.../ubuntu/+source/foobar
116 http://.../ubuntu/+source/mozilla-firefox121 http://.../ubuntu/+source/mozilla-firefox
117 http://.../ubuntu/+source/netapplet122 http://.../ubuntu/+source/netapplet
118 http://.../ubuntu/+source/alsa-utils
119 http://.../ubuntu/+source/foobar
120 http://.../ubuntu/+source/commercialpackage
121123
122"getArchive" returns a distribution archive (not a PPA) with the given name.124"getArchive" returns a distribution archive (not a PPA) with the given name.
123125
@@ -190,7 +192,6 @@
190 >>> antarctica_patch_target = webservice.named_get(192 >>> antarctica_patch_target = webservice.named_get(
191 ... ubuntu['self_link'], 'getMirrorByName',193 ... ubuntu['self_link'], 'getMirrorByName',
192 ... name='mirror.showa.antarctica.org-archive').jsonBody()194 ... name='mirror.showa.antarctica.org-archive').jsonBody()
193 ... )
194195
195 >>> response = karl_webservice.patch(196 >>> response = karl_webservice.patch(
196 ... antarctica_patch_target['self_link'], 'application/json',197 ... antarctica_patch_target['self_link'], 'application/json',
197198
=== modified file 'lib/lp/soyuz/browser/tests/distribution-views.txt'
--- lib/lp/soyuz/browser/tests/distribution-views.txt 2010-06-28 15:22:25 +0000
+++ lib/lp/soyuz/browser/tests/distribution-views.txt 2010-11-12 16:05:06 +0000
@@ -94,11 +94,11 @@
94 False94 False
95 >>> for package in distro_pkg_search_view.search_results:95 >>> for package in distro_pkg_search_view.search_results:
96 ... print package.name96 ... print package.name
97 netapplet
98 alsa-utils97 alsa-utils
98 commercialpackage
99 foobar99 foobar
100 mozilla-firefox100 mozilla-firefox
101 commercialpackage101 netapplet
102102
103Unless the distribution being searched does not support binaries, in which103Unless the distribution being searched does not support binaries, in which
104cases it will always be on source:104cases it will always be on source: