fix(teams): Deduplicate project features list#112326
Conversation
When a project belongs to multiple teams, the team serializer was passing duplicate Project objects into serialize(). This caused get_features_for_projects() to append features once per duplicate, so the features array multiplied by the number of teams a project was on. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| projects = [pt.project for pt in project_teams] | ||
|
|
||
| # A project can be on multiple teams, dedupe before serializing | ||
| projects = list({pt.project_id: pt.project for pt in project_teams}.values()) |
There was a problem hiding this comment.
it seems like this is the only user of get_for_teams_with_org_cache, we could in theory dedupe on the query level.
There was a problem hiding this comment.
(letting the clanker respond)
We still need the full join table for the project_map loop below (line 265-267) which maps each team to its projects. If we deduped at the query level we'd lose that team-to-project mapping. Could split it into two queries but that seems worse.
| # A project can be on multiple teams, dedupe before serializing | ||
| projects = list({pt.project_id: pt.project for pt in project_teams}.values()) | ||
|
|
||
| projects_by_id = { |
There was a problem hiding this comment.
we could also do this deduping after projects_by_id to make it a little cleaner
There was a problem hiding this comment.
(letting the clanker respond)
The dedup has to happen before serialize() — that's where get_features_for_projects() iterates the list and appends to a defaultdict(list) keyed by project. If duplicates are in the input, features get appended N times to the same list before projects_by_id ever gets built.
When a project belongs to multiple teams, the team serializer was building the projects list from the ProjectTeam join table without deduplicating. This meant `get_features_for_projects()` iterated the same project N times (once per team it belongs to), appending features to the same list each time. The features array in the response ended up with N copies of every feature. Deduplicates the project list before passing it to `serialize()`. You can see duplicates in the production endpoint https://us.sentry.io/api/0/organizations/sentry/teams/ --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When a project belongs to multiple teams, the team serializer was building the projects list from the ProjectTeam join table without deduplicating. This meant
get_features_for_projects()iterated the same project N times (once per team it belongs to), appending features to the same list each time. The features array in the response ended up with N copies of every feature.Deduplicates the project list before passing it to
serialize().You can see duplicates in the production endpoint https://us.sentry.io/api/0/organizations/sentry/teams/