Skip to content

feat(discover): add starred manager and endpoint for discover saved queries - #123795

Merged
lzhao-sentry merged 5 commits into
masterfrom
lzhao/feat/add-saved-query-starred-manager
Sep 9, 2026
Merged

feat(discover): add starred manager and endpoint for discover saved queries#123795
lzhao-sentry merged 5 commits into
masterfrom
lzhao/feat/add-saved-query-starred-manager

Conversation

@lzhao-sentry

@lzhao-sentry lzhao-sentry commented Sep 8, 2026

Copy link
Copy Markdown
Member

Changes

Addresses part of EXP-1166 in an effort to move remaining discover saved queries to All Queries tables. This PR adds/changes:

  • Starred manager for discover saved queries starred model
  • Associated endpoint to update a discover saved query's starred status (not public yet)
  • Tests for the endpoint
  • Fixed shared endpoint to handle reordering just like how Explore currently handles it

@linear-code

linear-code Bot commented Sep 8, 2026

Copy link
Copy Markdown

EXP-1166

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Sep 8, 2026
Comment thread src/sentry/discover/models.py Outdated
@lzhao-sentry
lzhao-sentry marked this pull request as ready for review September 8, 2026 20:58
@lzhao-sentry
lzhao-sentry requested a review from a team as a code owner September 8, 2026 20:58

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 02a75c7. Configure here.

Comment thread src/sentry/discover/models.py Outdated

@nikkikapadia nikkikapadia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a couple questions

},
)

assert response.status_code == 400

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we deleing this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually good point, we can keep it to test the serializer is catching it


with pytest.raises(ValueError, match="multiple positions"):
utils.reorder_starred_queries(self.org, self.user.id, [ref, ref])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above comment^

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not handled by the util function anymore

requested = list(refs)
if len(requested) != len(set(requested)):
raise ValueError("Single query cannot take up multiple positions.")
new_query_positions = list(refs)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this being removed because it's done somewhere else?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SavedQueryStarredOrderSerializer handles it, so it was redundant



@cell_silo_endpoint
class DiscoverSavedQueryStarredEndpoint(OrganizationEndpoint):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we able to put the actual endpoint in a different pr? in my head that makes sense but maybe i'm missing the reason we need it now.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can do that

Comment on lines +95 to +99
new_query_positions = list(refs)

# grab all starred queries in both tables, and map based on SavedQueryRef.
discover_starred_queries = DiscoverSavedQueryStarred.objects.filter(
organization=organization, user_id=user_id, position__isnull=False
).filter(organization=organization, user_id=user_id, position__isnull=False, starred=True)
organization=organization, user_id=user_id, position__isnull=False, starred=True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The reorder_starred_queries function incorrectly handles duplicate query references, as a flawed validation and dictionary comprehension lead to corrupted, non-contiguous position data being saved.
Severity: MEDIUM

Suggested Fix

Strengthen the validation within reorder_starred_queries to detect duplicates in the new_query_positions list before creating the position_map. A check like if len(new_query_positions) != len(set(new_query_positions)) should be added to the function to either raise a ValueError or to deduplicate the list explicitly, depending on the desired behavior.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/sentry/explore/utils.py#L95-L99

Potential issue: The function `reorder_starred_queries` incorrectly handles duplicate
query references in its input. The validation check `existing_query_refs !=
set(new_query_positions)` fails to detect duplicates because it converts the input list
to a set, eliminating duplicates before comparison. Subsequently, a dictionary
comprehension `position_map = {ref: position ...}` is used to assign positions, but it
silently overwrites the position for a duplicate reference with the last one it
encounters. This results in non-contiguous position values (e.g., positions 2 and 3 for
two queries) being saved to the database, corrupting the user's starred query order.
This can be triggered by any internal caller that bypasses the serializer validation
present in the HTTP endpoint.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THE SERIALIZER DOES THIS

@nikkikapadia nikkikapadia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚢

@lzhao-sentry
lzhao-sentry merged commit 7737ff4 into master Sep 9, 2026
71 checks passed
@lzhao-sentry
lzhao-sentry deleted the lzhao/feat/add-saved-query-starred-manager branch September 9, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants