|
24 | 24 | from sentry.users.services.user.service import user_service |
25 | 25 | from sentry.utils.event_frames import find_stack_frames, munged_filename_and_frames |
26 | 26 | from sentry.utils.hashlib import hash_values |
| 27 | +from sentry.utils.iterators import chunked |
27 | 28 |
|
28 | 29 | PATH_SEPARATORS = frozenset(["/", "\\"]) |
| 30 | +# Limit the number of commits to batch in a single query to avoid query timeouts |
| 31 | +# from large IN clauses combined with complex LIKE conditions |
| 32 | +COMMIT_BATCH_SIZE = 50 |
29 | 33 |
|
30 | 34 |
|
31 | 35 | def tokenize_path(path: str) -> Iterator[str]: |
@@ -96,11 +100,18 @@ def _get_commit_file_changes( |
96 | 100 | # build a single query to get all of the commit file that might match the first n frames |
97 | 101 | path_query = reduce(operator.or_, (Q(filename__iendswith=path) for path in filenames)) |
98 | 102 |
|
99 | | - commit_file_change_matches = CommitFileChange.objects.filter( |
100 | | - path_query, commit_id__in=[c.id for c in commits] |
101 | | - ) |
| 103 | + # Batch commits to avoid query timeouts from large IN clauses |
| 104 | + # combined with complex LIKE conditions |
| 105 | + all_file_changes: list[CommitFileChange] = [] |
| 106 | + commit_ids = [c.id for c in commits] |
| 107 | + |
| 108 | + for batch_commit_ids in chunked(commit_ids, COMMIT_BATCH_SIZE): |
| 109 | + commit_file_change_matches = CommitFileChange.objects.filter( |
| 110 | + path_query, commit_id__in=batch_commit_ids |
| 111 | + ) |
| 112 | + all_file_changes.extend(list(commit_file_change_matches)) |
102 | 113 |
|
103 | | - return list(commit_file_change_matches) |
| 114 | + return all_file_changes |
104 | 115 |
|
105 | 116 |
|
106 | 117 | def _match_commits_paths( |
|
0 commit comments