Merge lp:~stevenk/launchpad/fix-rasj-and-branches into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Steve Kowalik
Approved revision: no longer in the source branch.
Merged at revision: 15623
Proposed branch: lp:~stevenk/launchpad/fix-rasj-and-branches
Merge into: lp:launchpad
Diff against target: 172 lines (+50/-24)
3 files modified
lib/lp/code/model/branch.py (+11/-2)
lib/lp/registry/model/sharingjob.py (+27/-22)
lib/lp/registry/tests/test_sharingjob.py (+12/-0)
To merge this branch: bzr merge lp:~stevenk/launchpad/fix-rasj-and-branches
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
Review via email: mp+114779@code.launchpad.net

Commit message

Fix RemoveArtifactSubscriptionsJob to deal with branches correctly, and create a job in IBranch.transitionToInformationType().

Description of the change

While QAing the changes introduced in https://code.launchpad.net/~stevenk/launchpad/teach-rasj-about-branches/+merge/114106, William and I discovered that RASJ misbehaves if you don't pass any branches -- it will correctly deal with bug subscriptions, but then constructs a query that will take approximately three eons to complete on QAS, and then remove all subscriptions for that user from any branch. This is obviously bad.

I have reflowed the run() method to boot so that it won't deal with branches unless it needs to, and same with bugs, as well as sprinkling a branch into the bugs test and a bug into the branches test.

I have also noticed that IBranch.transitionToInformationType() does not create a job, so have added that in along with fixing some lint.

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Looks great.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/model/branch.py'
2--- lib/lp/code/model/branch.py 2012-07-13 00:17:32 +0000
3+++ lib/lp/code/model/branch.py 2012-07-13 04:58:27 +0000
4@@ -2,7 +2,6 @@
5 # GNU Affero General Public License version 3 (see the file LICENSE).
6
7 # pylint: disable-msg=E0611,W0212,W0141,F0401
8-from lp.registry.interfaces.product import IProduct
9
10 __metaclass__ = type
11 __all__ = [
12@@ -145,10 +144,12 @@
13 IAccessArtifactSource,
14 )
15 from lp.registry.interfaces.person import (
16- PersonVisibility,
17 validate_person,
18 validate_public_person,
19 )
20+from lp.registry.interfaces.sharingjob import (
21+ IRemoveArtifactSubscriptionsJobSource,
22+ )
23 from lp.registry.model.accesspolicy import (
24 AccessPolicyGrant,
25 reconcile_access_for_artifact,
26@@ -172,6 +173,7 @@
27 ArrayAgg,
28 ArrayIntersects,
29 )
30+from lp.services.features import getFeatureFlag
31 from lp.services.helpers import shortlist
32 from lp.services.job.interfaces.job import JobStatus
33 from lp.services.job.model.job import Job
34@@ -271,6 +273,13 @@
35 service.ensureAccessGrants(
36 blind_subscribers, who, branches=[self],
37 ignore_permissions=True)
38+ flag = 'disclosure.unsubscribe_jobs.enabled'
39+ if bool(getFeatureFlag(flag)):
40+ # As a result of the transition, some subscribers may no longer
41+ # have access to the branch. We need to run a job to remove any
42+ # such subscriptions.
43+ getUtility(IRemoveArtifactSubscriptionsJobSource).create(
44+ who, [self])
45
46 registrant = ForeignKey(
47 dbName='registrant', foreignKey='Person',
48
49=== modified file 'lib/lp/registry/model/sharingjob.py'
50--- lib/lp/registry/model/sharingjob.py 2012-07-11 01:24:30 +0000
51+++ lib/lp/registry/model/sharingjob.py 2012-07-13 04:58:27 +0000
52@@ -344,19 +344,13 @@
53 logger = logging.getLogger()
54 logger.info(self.getOperationDescription())
55
56- # Find all bug subscriptions for which the subscriber cannot see the
57- # bug.
58- bug_invisible_filter = Not(
59- Or(*get_bug_privacy_filter_terms(BugSubscription.person_id)))
60- bug_filters = [bug_invisible_filter]
61- branch_invisible_filter = Not(
62- Or(*get_branch_privacy_filter(BranchSubscription.personID)))
63- branch_filters = [branch_invisible_filter]
64+ bug_filters = []
65+ branch_filters = []
66
67+ if self.branch_ids:
68+ branch_filters.append(Branch.id.is_in(self.branch_ids))
69 if self.bug_ids:
70 bug_filters.append(BugTaskFlat.bug_id.is_in(self.bug_ids))
71- elif self.branch_ids:
72- branch_filters.append(Branch.id.is_in(self.branch_ids))
73 else:
74 if self.information_types:
75 bug_filters.append(
76@@ -385,15 +379,26 @@
77 TeamParticipation.personID,
78 where=TeamParticipation.team == self.grantee)))
79
80- bug_subscriptions = IStore(BugSubscription).using(
81- BugSubscription,
82- Join(BugTaskFlat, BugTaskFlat.bug_id == BugSubscription.bug_id)
83- ).find(BugSubscription, *bug_filters).config(distinct=True)
84- branch_subscriptions = IStore(BranchSubscription).find(
85- BranchSubscription, *branch_filters).config(distinct=True)
86- for sub in bug_subscriptions:
87- sub.bug.unsubscribe(
88- sub.person, self.requestor, ignore_permissions=True)
89- for sub in branch_subscriptions:
90- sub.branch.unsubscribe(
91- sub.person, self.requestor, ignore_permissions=True)
92+ if bug_filters:
93+ bug_filters.append(Not(
94+ Or(*get_bug_privacy_filter_terms(
95+ BugSubscription.person_id))))
96+ bug_subscriptions = IStore(BugSubscription).using(
97+ BugSubscription,
98+ Join(BugTaskFlat,
99+ BugTaskFlat.bug_id == BugSubscription.bug_id)
100+ ).find(BugSubscription, *bug_filters).config(distinct=True)
101+ for sub in bug_subscriptions:
102+ sub.bug.unsubscribe(
103+ sub.person, self.requestor, ignore_permissions=True)
104+ if branch_filters:
105+ branch_filters.append(Not(
106+ Or(*get_branch_privacy_filter(BranchSubscription.personID))))
107+ branch_subscriptions = IStore(BranchSubscription).using(
108+ BranchSubscription,
109+ Join(Branch, Branch.id == BranchSubscription.branchID)
110+ ).find(BranchSubscription, *branch_filters).config(
111+ distinct=True)
112+ for sub in branch_subscriptions:
113+ sub.branch.unsubscribe(
114+ sub.person, self.requestor, ignore_permissions=True)
115
116=== modified file 'lib/lp/registry/tests/test_sharingjob.py'
117--- lib/lp/registry/tests/test_sharingjob.py 2012-07-10 06:35:48 +0000
118+++ lib/lp/registry/tests/test_sharingjob.py 2012-07-13 04:58:27 +0000
119@@ -293,6 +293,9 @@
120 bug = self.factory.makeBug(
121 owner=owner, product=product,
122 information_type=InformationType.USERDATA)
123+ branch = self.factory.makeBranch(
124+ owner=owner, product=product,
125+ information_type=InformationType.USERDATA)
126
127 # The artifact grantees will not lose access when the job is run.
128 artifact_indirect_grantee = self.factory.makePerson()
129@@ -304,6 +307,9 @@
130 bug.subscribe(policy_indirect_grantee, owner)
131 bug.subscribe(artifact_team_grantee, owner)
132 bug.subscribe(artifact_indirect_grantee, owner)
133+ branch.subscribe(artifact_indirect_grantee,
134+ BranchSubscriptionNotificationLevel.NOEMAIL, None,
135+ CodeReviewNotificationLevel.NOEMAIL, owner)
136 # Subscribing policy_team_grantee has created an artifact grant so we
137 # need to revoke that to test the job.
138 getUtility(IAccessArtifactGrantSource).revokeByArtifact(
139@@ -332,6 +338,7 @@
140 self.assertNotIn(policy_indirect_grantee, subscribers)
141 self.assertIn(artifact_team_grantee, subscribers)
142 self.assertIn(artifact_indirect_grantee, subscribers)
143+ self.assertIn(artifact_indirect_grantee, branch.subscribers)
144
145 def _assert_branch_change_unsubscribes(self, change_callback):
146 product = self.factory.makeProduct()
147@@ -346,6 +353,9 @@
148
149 self.factory.makeAccessPolicyGrant(policy, policy_team_grantee, owner)
150 login_person(owner)
151+ bug = self.factory.makeBug(
152+ owner=owner, product=product,
153+ information_type=InformationType.USERDATA)
154 branch = self.factory.makeBranch(
155 owner=owner, product=product,
156 information_type=InformationType.USERDATA)
157@@ -371,6 +381,7 @@
158 artifact_indirect_grantee,
159 BranchSubscriptionNotificationLevel.NOEMAIL, None,
160 CodeReviewNotificationLevel.NOEMAIL, owner)
161+ bug.subscribe(artifact_indirect_grantee, owner)
162 # Subscribing policy_team_grantee has created an artifact grant so we
163 # need to revoke that to test the job.
164 getUtility(IAccessArtifactGrantSource).revokeByArtifact(
165@@ -398,6 +409,7 @@
166 self.assertNotIn(policy_indirect_grantee, branch.subscribers)
167 self.assertIn(artifact_team_grantee, branch.subscribers)
168 self.assertIn(artifact_indirect_grantee, branch.subscribers)
169+ self.assertIn(artifact_indirect_grantee, bug.getDirectSubscribers())
170
171 def test_change_information_type_branch(self):
172 def change_information_type(branch):