diff --git a/src/sentry/tasks/auto_ongoing_issues.py b/src/sentry/tasks/auto_ongoing_issues.py index 744cc4ef5498d1..80969421f0f0b3 100644 --- a/src/sentry/tasks/auto_ongoing_issues.py +++ b/src/sentry/tasks/auto_ongoing_issues.py @@ -109,31 +109,15 @@ def schedule_auto_transition_issues_new_to_ongoing( to be updated in a single run. However, we expect every instantiation of this task to chip away at the backlog of Groups and eventually update all the eligible groups. """ - span = sentry_sdk.Hub.current.scope.span total_count = 0 def get_total_count(results): nonlocal total_count total_count += len(results) - most_recent_group_first_seen_seven_days_ago = ( - Group.objects.filter( - first_seen__lte=datetime.fromtimestamp(first_seen_lte, timezone.utc), - ) - .order_by("-id") - .first() - ) - - if span is not None: - span.set_tag( - "most_recent_group_first_seen_seven_days_ago", - most_recent_group_first_seen_seven_days_ago.id, - ) - logger.info( "auto_transition_issues_new_to_ongoing started", extra={ - "most_recent_group_first_seen_seven_days_ago": most_recent_group_first_seen_seven_days_ago.id, "first_seen_lte": first_seen_lte, }, ) @@ -141,7 +125,7 @@ def get_total_count(results): base_queryset = Group.objects.filter( status=GroupStatus.UNRESOLVED, substatus=GroupSubStatus.NEW, - id__lte=most_recent_group_first_seen_seven_days_ago.id, + first_seen__lte=datetime.fromtimestamp(first_seen_lte, timezone.utc), ) with sentry_sdk.start_span(description="iterate_chunked_group_ids"): diff --git a/tests/sentry/tasks/test_auto_ongoing_issues.py b/tests/sentry/tasks/test_auto_ongoing_issues.py index 253c1a9cfb130c..871bb232ae10e1 100644 --- a/tests/sentry/tasks/test_auto_ongoing_issues.py +++ b/tests/sentry/tasks/test_auto_ongoing_issues.py @@ -208,6 +208,56 @@ def test_not_all_groups_get_updated(self, mock_backend, mock_metrics_incr): tags={"count": 0}, ) + @freeze_time("2023-07-12 18:40:00Z") + @mock.patch("sentry.tasks.auto_ongoing_issues.backend") + def test_unordered_ids(self, mock_backend): + """ + Group ids can be non-chronological with first_seen time (ex. as a result of merging). + Test that in this case, only groups that are >= TRANSITION_AFTER_DAYS days old are + transitioned. + """ + now = datetime.now(tz=timezone.utc) + organization = self.organization + project = self.create_project(organization=organization) + + # Create group with id x and first_seen < TRANSITION_AFTER_DAYS + group_new = self.create_group( + project=project, status=GroupStatus.UNRESOLVED, substatus=GroupSubStatus.NEW + ) + group_new.first_seen = now - timedelta(days=TRANSITION_AFTER_DAYS - 1, hours=1) + group_new.save() + + # Create group with id x+1 and first_seen > TRANSITION_AFTER_DAYS + # This could happen if an older group is merged into a newer group + group_old = self.create_group( + project=project, status=GroupStatus.UNRESOLVED, substatus=GroupSubStatus.NEW + ) + group_old.first_seen = now - timedelta(days=TRANSITION_AFTER_DAYS, hours=1) + group_old.save() + + mock_backend.get_size.return_value = 0 + + with self.tasks(): + schedule_auto_transition_to_ongoing() + + group_new.refresh_from_db() + assert group_new.status == GroupStatus.UNRESOLVED + assert group_new.substatus == GroupSubStatus.NEW + + group_old.refresh_from_db() + assert group_old.status == GroupStatus.UNRESOLVED + assert group_old.substatus == GroupSubStatus.ONGOING + assert not GroupInbox.objects.filter(group=group_old).exists() + + set_ongoing_activity = Activity.objects.filter( + group=group_old, type=ActivityType.AUTO_SET_ONGOING.value + ).get() + assert set_ongoing_activity.data == {"after_days": 7} + + assert GroupHistory.objects.filter( + group=group_old, status=GroupHistoryStatus.ONGOING + ).exists() + @apply_feature_flag_on_cls("organizations:escalating-issues") class ScheduleAutoRegressedOngoingIssuesTest(TestCase):