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(shared-views): Add groupsearchview starred endpoint for reordering #87347

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

MichaelSun48
Copy link
Member

This PR adds the PUT /group-search-views-starred-order/ endpoint.

This endpoint is akin to a pared down version of the old PUT /group-search-views/ endpoint, which used to bulk update every aspect of the view, including filter parameters like query, sort, and projects. This new endpoint no longer handles any filter parameter changes (that will be delegated to a PUT /group-search-views/:viewId endpoint), but does handle bulk adding, removing, and reordering starred views.

The logic at a high level is:

  1. Accept a list of viewIds from the client, where the position of the viewId in the list is the new position
  2. Run validation on the viewIds
  3. Delete any GroupSearchViewStarred entries that are no longer in the request list (they must have been removed)
  4. Update the positions for any GroupSearchViewStarred entries that exist in the list
  5. Create new GroupSearchViewStarred entries for views that did not already have them.

@MichaelSun48 MichaelSun48 requested review from a team as code owners March 18, 2025 21:22
@MichaelSun48 MichaelSun48 requested a review from a team March 18, 2025 21:22
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Mar 18, 2025
Copy link

codecov bot commented Mar 18, 2025

❌ 5 Tests Failed:

Tests completed Failed Passed Skipped
24427 5 24422 299
View the top 3 failed test(s) by shortest run time
tests.sentry.api.endpoints.test_organization_spans_fields_stats.OrganizationSpansFieldsStatsEndpointTest::test_filter_query
Stack Traces | 5.58s run time
#x1B[1m#x1B[.../api/endpoints/test_organization_spans_fields_stats.py#x1B[0m:157: in test_filter_query
    assert distributions[0]["attributeName"] == "broswer"
#x1B[1m#x1B[31mE   AssertionError: assert 'sentry.transaction' == 'broswer'#x1B[0m
#x1B[1m#x1B[31mE     #x1B[0m
#x1B[1m#x1B[31mE     - broswer#x1B[0m
#x1B[1m#x1B[31mE     + sentry.transaction#x1B[0m
tests.sentry.api.endpoints.test_organization_spans_fields_stats.OrganizationSpansFieldsStatsEndpointTest::test_max_buckets
Stack Traces | 6.25s run time
#x1B[1m#x1B[.../api/endpoints/test_organization_spans_fields_stats.py#x1B[0m:117: in test_max_buckets
    assert len(distributions) == max_buckets - 1
#x1B[1m#x1B[31mE   AssertionError: assert 1 == (3 - 1)#x1B[0m
#x1B[1m#x1B[31mE    +  where 1 = len([{'label': 'foo', 'value': 3.0}])#x1B[0m
tests.snuba.tagstore.test_tagstore_backend.TagStorageTest::test_get_group_tag_key_generic
Stack Traces | 7.3s run time
#x1B[1m#x1B[.../snuba/tagstore/test_tagstore_backend.py#x1B[0m:554: in test_get_group_tag_key_generic
    assert (
#x1B[1m#x1B[.../tagstore/snuba/backend.py#x1B[0m:479: in get_group_tag_key
    return self.__get_tag_key_and_top_values(
#x1B[1m#x1B[.../tagstore/snuba/backend.py#x1B[0m:207: in __get_tag_key_and_top_values
    raise TagKeyNotFound if group is None else GroupTagKeyNotFound
#x1B[1m#x1B[31mE   sentry.tagstore.exceptions.GroupTagKeyNotFound#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

try:
gsvs = GroupSearchView.objects.filter(
organization=self.context["organization"], id__in=view_ids
)
Copy link
Member

@JoshFerge JoshFerge Mar 18, 2025

Choose a reason for hiding this comment

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

could use .values(...) here to make the query a bit more efficient by returning less data.

it is also probably good to do validation here that all the gsvs exist. that is, check the length of view_ids against the returned query.

Copy link
Member

Choose a reason for hiding this comment

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

oh i guess it not existing is valid input, since we create it below

return Response(status=status.HTTP_204_NO_CONTENT)


def _update_view_positions(organization: Organization, user_id: int, view_positions: list[int]):
Copy link
Member

Choose a reason for hiding this comment

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

this method might make sense to live on the object manager of GroupSearchViewStarred.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed, but I don't want to add that abstraction if this will be the only place that uses this functionality, which I suspect will be the case. I'll definitely keep the model managers abstraction in mind in the future though, i agree they can be very useful.

starred_view.group_search_view_id: starred_view for starred_view in existing_starred_views
}

for idx, view_id in enumerate(view_positions):
Copy link
Member

Choose a reason for hiding this comment

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

at some point we'll probably want to do bulk operations instead of creating / updating one by one, as if you have 100+ views this could end up being a bit slow. on a related note, is there a cap to how many starred views someone could have?

Copy link
Member Author

Choose a reason for hiding this comment

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

The PUT groupsearchview endpoint enforces a max of 50 views, which I think should be well below the threshold at which this would cause slowdowns.

Copy link
Member

Choose a reason for hiding this comment

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

worth thinking about what is considered "fast" or "snappy" and can observe endpoint to make sure it's within parameters after releasing!

existing_starred_views_dict[view_id].save()
else:
try:
GroupSearchViewStarred.objects.create(
Copy link
Member

Choose a reason for hiding this comment

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

Adding rows here seems unexpected. If I reorder some starred views I wouldn't want to star anything due to that action. IMO in this case we should either respond with a 400 or filter out the starred rows that don't exist

Copy link
Member Author

Choose a reason for hiding this comment

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

Reordering your starred views shouldn't cause this create to fire. This would only fire if someone an existing view is starred.

@MichaelSun48
Copy link
Member Author

Renaming this to groupsearchviewstarred (rather than groupsearchviewstarredorder) since this can endpoint does more than just reordering

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.

3 participants