|
2 | 2 | from datetime import datetime, timedelta, timezone |
3 | 3 |
|
4 | 4 | import sentry_sdk |
5 | | -from django.db.models import Max |
| 5 | +from django.db.models import Max, OuterRef, Subquery |
6 | 6 |
|
7 | 7 | from sentry.issues.ongoing import TRANSITION_AFTER_DAYS, bulk_transition_group_to_ongoing |
8 | 8 | from sentry.models.group import Group, GroupStatus |
9 | | -from sentry.models.grouphistory import GroupHistoryStatus |
| 9 | +from sentry.models.grouphistory import GroupHistory, GroupHistoryStatus |
10 | 10 | from sentry.silo.base import SiloMode |
11 | 11 | from sentry.tasks.base import instrumented_task |
12 | 12 | from sentry.taskworker.namespaces import issues_tasks |
@@ -163,14 +163,28 @@ def get_total_count(results): |
163 | 163 | nonlocal total_count |
164 | 164 | total_count += len(results) |
165 | 165 |
|
| 166 | + date_threshold = datetime.fromtimestamp(date_added_lte, timezone.utc) |
| 167 | + |
| 168 | + # Use a subquery to get the most recent REGRESSED history date for each group. |
| 169 | + # This ensures we only transition groups whose MOST RECENT regressed history |
| 170 | + # is older than the threshold, not just any regressed history. |
| 171 | + latest_regressed_subquery = ( |
| 172 | + GroupHistory.objects.filter(group_id=OuterRef("id"), status=GroupHistoryStatus.REGRESSED) |
| 173 | + .values("group_id") |
| 174 | + .annotate(max_date=Max("date_added")) |
| 175 | + .values("max_date")[:1] |
| 176 | + ) |
| 177 | + |
166 | 178 | base_queryset = ( |
167 | 179 | Group.objects.filter( |
168 | 180 | status=GroupStatus.UNRESOLVED, |
169 | 181 | substatus=GroupSubStatus.REGRESSED, |
170 | | - grouphistory__status=GroupHistoryStatus.REGRESSED, |
171 | 182 | ) |
172 | | - .annotate(recent_regressed_history=Max("grouphistory__date_added")) |
173 | | - .filter(recent_regressed_history__lte=datetime.fromtimestamp(date_added_lte, timezone.utc)) |
| 183 | + .annotate(recent_regressed_history=Subquery(latest_regressed_subquery)) |
| 184 | + .filter( |
| 185 | + recent_regressed_history__lte=date_threshold, |
| 186 | + recent_regressed_history__isnull=False, |
| 187 | + ) |
174 | 188 | ) |
175 | 189 |
|
176 | 190 | with sentry_sdk.start_span(name="iterate_chunked_group_ids"): |
@@ -244,14 +258,30 @@ def get_total_count(results): |
244 | 258 | nonlocal total_count |
245 | 259 | total_count += len(results) |
246 | 260 |
|
| 261 | + from django.db.models import Max, OuterRef, Subquery |
| 262 | + |
| 263 | + date_threshold = datetime.fromtimestamp(date_added_lte, timezone.utc) |
| 264 | + |
| 265 | + # Use a subquery to get the most recent ESCALATING history date for each group. |
| 266 | + # This ensures we only transition groups whose MOST RECENT escalating history |
| 267 | + # is older than the threshold, not just any escalating history. |
| 268 | + latest_escalating_subquery = ( |
| 269 | + GroupHistory.objects.filter(group_id=OuterRef("id"), status=GroupHistoryStatus.ESCALATING) |
| 270 | + .values("group_id") |
| 271 | + .annotate(max_date=Max("date_added")) |
| 272 | + .values("max_date")[:1] |
| 273 | + ) |
| 274 | + |
247 | 275 | base_queryset = ( |
248 | 276 | Group.objects.filter( |
249 | 277 | status=GroupStatus.UNRESOLVED, |
250 | 278 | substatus=GroupSubStatus.ESCALATING, |
251 | | - grouphistory__status=GroupHistoryStatus.ESCALATING, |
252 | 279 | ) |
253 | | - .annotate(recent_escalating_history=Max("grouphistory__date_added")) |
254 | | - .filter(recent_escalating_history__lte=datetime.fromtimestamp(date_added_lte, timezone.utc)) |
| 280 | + .annotate(recent_escalating_history=Subquery(latest_escalating_subquery)) |
| 281 | + .filter( |
| 282 | + recent_escalating_history__lte=date_threshold, |
| 283 | + recent_escalating_history__isnull=False, |
| 284 | + ) |
255 | 285 | ) |
256 | 286 |
|
257 | 287 | with sentry_sdk.start_span(name="iterate_chunked_group_ids"): |
|
0 commit comments