Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(team-workflow): Update bulk_subscribe to accept teams #55943

Merged
merged 10 commits into from
Sep 13, 2023
37 changes: 31 additions & 6 deletions src/sentry/models/groupsubscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,28 @@ def subscribe_actor(
else:
# subscribe the members of the team
team_users_ids = list(actor.member_set.values_list("user_id", flat=True))
return self.bulk_subscribe(group, team_users_ids, reason)
return self.bulk_subscribe(group=group, user_ids=team_users_ids, reason=reason)

raise NotImplementedError("Unknown actor type: %r" % type(actor))

def bulk_subscribe(
self,
group: Group,
user_ids: Iterable[int],
user_ids: Iterable[int] | None = None,
team_ids: Iterable[int] | None = None,
reason: int = GroupSubscriptionReason.unknown,
) -> bool:
"""
Subscribe a list of user ids to an issue, but only if the users are not explicitly
Subscribe a list of user ids and/or teams to an issue, but only if the users/teams are not explicitly
unsubscribed.
"""
from sentry import features

# Unique the IDs.
user_ids = set(user_ids)
user_ids = set(user_ids) if user_ids else set()

# Unique the teams.
team_ids = set(team_ids) if team_ids else set()

# 5 retries for race conditions where
# concurrent subscription attempts cause integrity errors
Expand All @@ -117,10 +123,29 @@ def bulk_subscribe(
is_active=True,
reason=reason,
)
for user_id in user_ids
if user_id not in existing_subscriptions
for user_id in user_ids.difference(existing_subscriptions)
]

if features.has("organizations:team-workflow-notifications", group.organization):
existing_team_subscriptions = set(
GroupSubscription.objects.filter(
team_id__in=team_ids, group=group, project=group.project
).values_list("team_id", flat=True)
)

subscriptions.extend(
[
GroupSubscription(
team_id=team_id,
group=group,
project=group.project,
is_active=True,
reason=reason,
)
for team_id in team_ids.difference(existing_team_subscriptions)
]
)

try:
with transaction.atomic(router.db_for_write(GroupSubscription)):
self.bulk_create(subscriptions)
Expand Down
71 changes: 70 additions & 1 deletion tests/sentry/models/test_groupsubscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_bulk(self):
group = self.create_group()

user_ids = []
for i in range(20):
for _ in range(20):
user = self.create_user()
user_ids.append(user.id)

Expand Down Expand Up @@ -71,6 +71,75 @@ def test_bulk_dupes(self):

assert len(GroupSubscription.objects.filter(group=group)) == 1

@with_feature("organizations:team-workflow-notifications")
def test_bulk_teams(self):
group = self.create_group()

team_ids = []
for _ in range(20):
team = self.create_team()
team_ids.append(team.id)

GroupSubscription.objects.bulk_subscribe(group=group, team_ids=team_ids)

assert len(GroupSubscription.objects.filter(group=group)) == 20

one_more = self.create_team()
team_ids.append(one_more.id)

# should not error
GroupSubscription.objects.bulk_subscribe(group=group, team_ids=team_ids)

assert len(GroupSubscription.objects.filter(group=group)) == 21

@with_feature("organizations:team-workflow-notifications")
def test_bulk_teams_dupes(self):
group = self.create_group()

team_ids = []

team = self.create_team()
team_ids.append(team.id)
team_ids.append(team.id)

GroupSubscription.objects.bulk_subscribe(group=group, team_ids=team_ids)

assert len(GroupSubscription.objects.filter(group=group)) == 1

@with_feature("organizations:team-workflow-notifications")
def test_bulk_users_and_teams(self):
group = self.create_group()

user_ids = []
team_ids = []

for _ in range(10):
user = self.create_user()
user_ids.append(user.id)
team = self.create_team()
team_ids.append(team.id)

GroupSubscription.objects.bulk_subscribe(group=group, user_ids=user_ids, team_ids=team_ids)

assert len(GroupSubscription.objects.filter(group=group)) == 20

@with_feature("organizations:team-workflow-notifications")
def test_bulk_user_on_team(self):
"""
Test that ensures bulk_subscribe subscribes users and teams individually, even if one of those users is part of one of those teams.
"""
group = self.create_group()
team = self.create_team()
user = self.create_user()
self.create_member(user=user, organization=self.organization, role="member", teams=[team])

team_ids = [team.id]
user_ids = [user.id]

GroupSubscription.objects.bulk_subscribe(group=group, user_ids=user_ids, team_ids=team_ids)

assert len(GroupSubscription.objects.filter(group=group)) == 2

def test_actor_user(self):
group = self.create_group()
user = self.create_user()
Expand Down
Loading