ref(issues): Batch requests for non-error groups - #121018
Conversation
|
@cursor review this pr |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bd6ce7e. Configure here.
5b2de8a to
7889e8c
Compare
| except UnsupportedSearchQuery: | ||
| continue | ||
|
|
||
| if merge_generic_categories and group_category != GroupCategory.ERROR.value: |
There was a problem hiding this comment.
don't love how much this is changing vs what's happening today; the tl;dr is that it's just building a reference dict that can be used the same way as we do today or batch the generic categories. 🤔
kcons
left a comment
There was a problem hiding this comment.
Mostly educating myself, since I don't know this code. It looks pretty reasonable, I need to look a bit more to feel confident.
| # Get the top matching groups by score, i.e. the actual search results | ||
| # in the order that we want them. | ||
| orderby = [f"-{sort_field}", "group_id"] # ensure stable sort within the same score | ||
| group_id_sort = "-group_id" if len(group_categories) > 1 else "group_id" |
There was a problem hiding this comment.
why do we reverse for multiple categories?
There was a problem hiding this comment.
The merged query needs to match the downstream SequencePaginator, which sorts (score, group_id) with reverse=True; equal-score rows are therefore consumed by descending group_id. Once multiple categories share one Snuba LIMIT/OFFSET, fetching ties in ascending ID order would select the opposite end of the tie block and can skip or repeat rows across pages. The singleton path stays ascending to preserve the existing behavior (and EAP comparison) while the feature flag is off. The conditional is non-obvious, but the pagination test exercises it.
| conditions.append(converted_filter) | ||
|
|
||
| use_issue_platform = group_category is not GroupCategory.ERROR.value | ||
| use_issue_platform = GroupCategory.ERROR.value not in group_categories |
There was a problem hiding this comment.
we only use issue platform if we're not searching for errors.. which means we can choose to use issue platform or not for other categories and we're okay making errors determine that vs using more queries?
There was a problem hiding this comment.
This is not choosing the dataset for a mixed error/generic query. Error is explicitly excluded from category merging above, and get_search_strategy asserts that ERROR cannot appear with generic categories. So the only inputs here are [ERROR], which uses Events, or one or more non-error categories, which use Issue Platform. Errors still get their own query and do not force other categories onto Events.
| continue | ||
|
|
||
| if query_params is not None: | ||
| query_params_for_categories[tuple(grouped_categories)] = query_params |
There was a problem hiding this comment.
there may be an argument for factoring out a function that returns query_params_for_categories.
There was a problem hiding this comment.
I considered this, but _prepare_params_for_categories already owns construction of each SnubaQueryParams; extracting the full loop would mostly move the same long argument list into another method. The genuinely new part is building category_filter_groups, so that is the smaller extraction I would make if we want to shorten snuba_search further.
tl;dr, it felt important to keep this as focused fix to try and fix the N+1 issue; i think we could do quite a bit of cleanup work here.
| merge_generic_categories = features.has( | ||
| "organizations:issue-search-merged-generic-query", organization, actor=actor | ||
| ) | ||
| category_filter_groups: list[tuple[list[int], Sequence[SearchFilter]]] = [] |
There was a problem hiding this comment.
no better type to be had here?
There was a problem hiding this comment.
i had actually refactored it to: list[tuple[list[GroupCategory], Sequence[SearchFilter]]] but that required a bunch of other changes -- needing to refactor a few other areas in this. i ended up reverting that diff because i wanted to keep the change focused to fixing the query problem.
can def bring that back if you feel strongly, was just trying to balance the number of changes outside of the rollout flag.

Description
Update the
_prepare_params_for_categoryto be a batch method. Instead of producing filters such as:it produces one union:
Allowing us to make 1 query for errors, and 1 query for all other types; where previously we had 7 total concurrent queries.
Uses
organizations:issue-search-merged-generic-queryas a feature flag to safely rollout the changes.Dashboard to monitor impact and rollout