launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #17530
[Merge] lp:~wgrant/launchpad/bug-1393549 into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/bug-1393549 into lp:launchpad.
Commit message:
Preload API attributes when findTeam is invoked from the API. And preload teamowner when preloading Persons for the API.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1393549 in Launchpad itself: "Timeout when calling findTeam over the API"
https://bugs.launchpad.net/launchpad/+bug/1393549
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bug-1393549/+merge/242033
Preload API attributes when findTeam is invoked from the API. And preload teamowner when preloading Persons for the API.
--
https://code.launchpad.net/~wgrant/launchpad/bug-1393549/+merge/242033
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bug-1393549 into lp:launchpad.
=== modified file 'lib/lp/registry/browser/tests/test_person_webservice.py'
--- lib/lp/registry/browser/tests/test_person_webservice.py 2014-10-22 17:20:27 +0000
+++ lib/lp/registry/browser/tests/test_person_webservice.py 2014-11-17 23:51:02 +0000
@@ -153,6 +153,23 @@
self.assertReturnsPeople(
[team_name], '/people?ws.op=findTeam&text=%s' % person_name)
+ def test_findTeam_query_count(self):
+ with admin_logged_in():
+ ws = webservice_for_person(self.factory.makePerson())
+
+ def create_match():
+ with admin_logged_in():
+ self.factory.makeTeam(displayname='foobar')
+
+ def find_teams():
+ ws.named_get('/people', 'findTeam', text="foobar").jsonBody()
+
+ # Ensure that we're already in a stable cache state.
+ find_teams()
+ recorder1, recorder2 = record_two_runs(
+ find_teams, create_match, 2)
+ self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+
def test_findPerson(self):
# The search can be restricted to people.
with admin_logged_in():
=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py 2014-10-22 16:20:30 +0000
+++ lib/lp/registry/interfaces/person.py 2014-11-17 23:51:02 +0000
@@ -2269,12 +2269,13 @@
restrict the search to the dates provided.
"""
+ @call_with(preload_for_api=True)
@operation_parameters(
text=TextLine(title=_("Search text"), default=u""))
@operation_returns_collection_of(IPerson)
@export_read_operation()
@operation_for_version("beta")
- def findTeam(text=""):
+ def findTeam(text="", preload_for_api=False):
"""Return all Teams whose name, displayname or email address
match <text>.
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2014-10-22 19:10:06 +0000
+++ lib/lp/registry/model/person.py 2014-11-17 23:51:02 +0000
@@ -3658,7 +3658,7 @@
combined_results = email_results.union(name_results)
return combined_results.order_by(orderBy)
- def findTeam(self, text=""):
+ def findTeam(self, text="", preload_for_api=False):
"""See `IPersonSet`."""
orderBy = Person._sortingColumnsForSetOperations
text = ensure_unicode(text)
@@ -3670,8 +3670,13 @@
email_results = store.find(Person, email_query).order_by()
name_query = self._teamNameQuery(text)
name_results = store.find(Person, name_query).order_by()
- combined_results = email_results.union(name_results)
- return combined_results.order_by(orderBy)
+ result = email_results.union(name_results).order_by(orderBy)
+ if preload_for_api:
+ def preload(people):
+ list(self.getPrecachedPersonsFromIDs(
+ [person.id for person in people], need_api=True))
+ result = DecoratedResultSet(result, pre_iter_hook=preload)
+ return result
def get(self, personid):
"""See `IPersonSet`."""
@@ -3774,9 +3779,9 @@
def getPrecachedPersonsFromIDs(
self, person_ids, need_api=False, need_karma=False,
- need_ubuntu_coc=False, need_location=False, need_archive=False,
- need_preferred_email=False, need_validity=False,
- need_icon=False):
+ need_ubuntu_coc=False, need_teamowner=False, need_location=False,
+ need_archive=False, need_preferred_email=False,
+ need_validity=False, need_icon=False):
"""See `IPersonSet`."""
person_ids = set(person_ids)
person_ids.discard(None)
@@ -3786,16 +3791,16 @@
conditions = [
Person.id.is_in(person_ids)]
return self._getPrecachedPersons(
- origin, conditions, need_api=need_api,
- need_karma=need_karma, need_ubuntu_coc=need_ubuntu_coc,
+ origin, conditions, need_api=need_api, need_karma=need_karma,
+ need_ubuntu_coc=need_ubuntu_coc, need_teamowner=need_teamowner,
need_location=need_location, need_archive=need_archive,
need_preferred_email=need_preferred_email,
need_validity=need_validity, need_icon=need_icon)
def _getPrecachedPersons(
self, origin, conditions, store=None, need_api=False,
- need_karma=False, need_ubuntu_coc=False, need_location=False,
- need_archive=False, need_preferred_email=False,
+ need_karma=False, need_ubuntu_coc=False, need_teamowner=False,
+ need_location=False, need_archive=False, need_preferred_email=False,
need_validity=False, need_icon=False):
"""Lookup all members of the team with optional precaching.
@@ -3884,6 +3889,10 @@
columns = tuple(columns)
raw_result = store.using(*origin).find(columns, conditions)
+ def preload_for_people(rows):
+ if need_teamowner or need_api:
+ bulk.load(Person, [row[0].teamownerID for row in rows])
+
def prepopulate_person(row):
result = row[0]
cache = get_property_cache(result)
@@ -3923,6 +3932,7 @@
decorator(result, column)
return result
return DecoratedResultSet(raw_result,
+ pre_iter_hook=preload_for_people,
result_decorator=prepopulate_person)
=== modified file 'lib/lp/registry/tests/test_personset.py'
--- lib/lp/registry/tests/test_personset.py 2014-01-15 06:54:12 +0000
+++ lib/lp/registry/tests/test_personset.py 2014-11-17 23:51:02 +0000
@@ -5,6 +5,7 @@
__metaclass__ = type
+import transaction
from testtools.matchers import LessThan
from zope.component import getUtility
@@ -110,13 +111,15 @@
# query to load all the extraneous data. Accessing the
# attributes should then cause zero queries.
person_ids = [self.factory.makePerson().id for i in range(3)]
+ person_ids += [self.factory.makeTeam().id for i in range(3)]
+ transaction.commit()
with StormStatementRecorder() as recorder:
persons = list(self.person_set.getPrecachedPersonsFromIDs(
person_ids, need_karma=True, need_ubuntu_coc=True,
- need_location=True, need_archive=True,
+ need_teamowner=True, need_location=True, need_archive=True,
need_preferred_email=True, need_validity=True))
- self.assertThat(recorder, HasQueryCount(LessThan(2)))
+ self.assertThat(recorder, HasQueryCount(LessThan(3)))
with StormStatementRecorder() as recorder:
for person in persons:
@@ -126,6 +129,7 @@
person.location,
person.archive
person.preferredemail
+ person.teamowner
self.assertThat(recorder, HasQueryCount(LessThan(1)))
def test_getPrecachedPersonsFromIDs_is_ubuntu_coc_signer(self):
Follow ups