Merge lp:~sinzui/launchpad/fast-contact-via-web into lp:launchpad

Proposed by Curtis Hovey on 2012-11-29
Status: Merged
Approved by: j.c.sackett on 2012-11-29
Approved revision: no longer in the source branch.
Merged at revision: 16324
Proposed branch: lp:~sinzui/launchpad/fast-contact-via-web
Merge into: lp:launchpad
Diff against target: 55 lines (+14/-3)
2 files modified
lib/lp/registry/browser/person.py (+5/-1)
lib/lp/registry/browser/tests/test_person_contact.py (+9/-2)
To merge this branch: bzr merge lp:~sinzui/launchpad/fast-contact-via-web
Reviewer Review Type Date Requested Status
j.c.sackett (community) 2012-11-29 Approve on 2012-11-29
Review via email: mp+136986@code.launchpad.net

Commit Message

Do not load all the team members to learn the count of who will be contacted.

Description of the Change

OOPS-6c1d4799395a99f0d86db9e729eaab5d shows a timeout caused by lost
time in a python call related to getMembersWithPreferredEmails(). The
link to contact team members needs to know the count, but it is getting
all 18363 members -- they are not needed. A recent change to fix an oops
contact teams without admins changed the call to get the count to use a
cached property...but this property is not already loaded, and in fact
only needs to be called when sending the member email messages.

--------------------------------------------------------------------

RULES

    Pre-implementation: no one
    * Revert the change to ContactViaWebNotificationRecipientSet.__len__
      so that the TO_MEMBERS check uses:
      recipient.getMembersWithPreferredEmailsCount()
    * Keep the change for TO_ADMINS.

QA

    As a member of https://qastaging.launchpad.net/~ubuntu-lococouncil:
    * Visit https://qastaging.launchpad.net/~locoteams
    * Verify the page loads.

LINT

    lib/lp/registry/browser/person.py
    lib/lp/registry/browser/tests/test_person_contact.py

TEST

    ./bin/test -vvc lp.registry.browser.tests.test_person_contact

IMPLEMENTATION

I reverted the check for TO_MEMBERS which was much faster than the
needless loading of all the members. I forgot that pages that link to
the contact-team page use the ContactViaWebNotificationRecipientSet to
get the link description, they do not need the members, so they were not
already cached. I added a test to verify that instantiating the
recipient set and calling length makes less than three db calls -- it
currently checks the user's
relationship to the team, then gets the member count.
    lib/lp/registry/browser/person.py
    lib/lp/registry/browser/tests/test_person_contact.py

To post a comment you must log in.
j.c.sackett (jcsackett) wrote :

This looks good. Thanks, Curtis.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/person.py'
2--- lib/lp/registry/browser/person.py 2012-11-27 16:04:54 +0000
3+++ lib/lp/registry/browser/person.py 2012-11-29 16:45:34 +0000
4@@ -4066,7 +4066,11 @@
5 """The number of recipients in the set."""
6 if self._count_recipients is None:
7 recipient = self._primary_recipient
8- if self.primary_reason in (self.TO_MEMBERS, self.TO_ADMINS):
9+ if self.primary_reason is self.TO_MEMBERS:
10+ # Get the count without loading all the members.
11+ self._count_recipients = (
12+ recipient.getMembersWithPreferredEmailsCount())
13+ elif self.primary_reason is self.TO_ADMINS:
14 self._count_recipients = len(self._all_recipients)
15 elif recipient.is_valid_person_or_team:
16 self._count_recipients = 1
17
18=== modified file 'lib/lp/registry/browser/tests/test_person_contact.py'
19--- lib/lp/registry/browser/tests/test_person_contact.py 2012-11-27 19:43:48 +0000
20+++ lib/lp/registry/browser/tests/test_person_contact.py 2012-11-29 16:45:34 +0000
21@@ -4,6 +4,8 @@
22
23 __metaclass__ = type
24
25+from testtools.matchers import LessThan
26+
27 from lp.app.browser.tales import DateTimeFormatterAPI
28 from lp.registry.browser.person import (
29 ContactViaWebLinksMixin,
30@@ -13,9 +15,11 @@
31 from lp.services.messages.interfaces.message import IDirectEmailAuthorization
32 from lp.testing import (
33 person_logged_in,
34+ StormStatementRecorder,
35 TestCaseWithFactory,
36 )
37 from lp.testing.layers import DatabaseFunctionalLayer
38+from lp.testing.matchers import HasQueryCount
39 from lp.testing.views import create_initialized_view
40
41
42@@ -52,8 +56,11 @@
43 member = self.factory.makePerson()
44 sender_team = self.factory.makeTeam(members=[member])
45 owner = sender_team.teamowner
46- self.assertEqual(
47- 2, len(ContactViaWebNotificationRecipientSet(owner, sender_team)))
48+ with StormStatementRecorder() as recorder:
49+ total = len(
50+ ContactViaWebNotificationRecipientSet(owner, sender_team))
51+ self.assertThat(recorder, HasQueryCount(LessThan(3)))
52+ self.assertEqual(2, total)
53 with person_logged_in(owner):
54 owner.leave(sender_team)
55 self.assertEqual(