Skip to content

Commit 81e2427

Browse files
authored
fix(seer): Scan only new issues or issues without scans (#93867)
Only allow the scanner job to start if an issue is new or does not have an existing scan + summary.
1 parent 96f23c6 commit 81e2427

File tree

3 files changed

+121
-1
lines changed

3 files changed

+121
-1
lines changed

src/sentry/seer/issue_summary.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,10 @@ def _log_seer_scanner_billing_event(group: Group, source: SeerAutomationSource):
392392
)
393393

394394

395+
def get_issue_summary_cache_key(group_id: int) -> str:
396+
return f"ai-group-summary-v2:{group_id}"
397+
398+
395399
def get_issue_summary(
396400
group: Group,
397401
user: User | RpcUser | AnonymousUser | None = None,
@@ -418,7 +422,7 @@ def get_issue_summary(
418422
if not get_seer_org_acknowledgement(group.organization.id):
419423
return {"detail": "AI Autofix has not been acknowledged by the organization."}, 403
420424

421-
cache_key = f"ai-group-summary-v2:{group.id}"
425+
cache_key = get_issue_summary_cache_key(group.id)
422426
lock_key = f"ai-group-summary-v2-lock:{group.id}"
423427
lock_duration = 10 # How long the lock is held if acquired (seconds)
424428
wait_timeout = 4.5 # How long to wait for the lock (seconds)

src/sentry/tasks/post_process.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,12 +1558,21 @@ def check_if_flags_sent(job: PostProcessJob) -> None:
15581558

15591559

15601560
def kick_off_seer_automation(job: PostProcessJob) -> None:
1561+
from sentry.seer.issue_summary import get_issue_summary_cache_key
15611562
from sentry.seer.seer_setup import get_seer_org_acknowledgement
15621563
from sentry.tasks.autofix import start_seer_automation
15631564

15641565
event = job["event"]
15651566
group = event.group
15661567

1568+
# Only run on new issues or issues with no existing summary/scan
1569+
if (
1570+
not job["group_state"]["is_new"]
1571+
and group.seer_fixability_score is not None
1572+
and cache.get(get_issue_summary_cache_key(group.id))
1573+
):
1574+
return
1575+
15671576
# check currently supported issue categories for Seer
15681577
if group.issue_category not in [
15691578
GroupCategory.ERROR,

tests/sentry/tasks/test_post_process.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,6 +2575,113 @@ def test_kick_off_seer_automation_without_scanner_on(
25752575

25762576
mock_start_seer_automation.assert_not_called()
25772577

2578+
@patch(
2579+
"sentry.seer.seer_setup.get_seer_org_acknowledgement",
2580+
return_value=True,
2581+
)
2582+
@patch("sentry.tasks.autofix.start_seer_automation.delay")
2583+
@with_feature("organizations:gen-ai-features")
2584+
@with_feature("organizations:trigger-autofix-on-issue-summary")
2585+
def test_kick_off_seer_automation_skips_existing_summary_and_score(
2586+
self, mock_start_seer_automation, mock_get_seer_org_acknowledgement
2587+
):
2588+
from sentry.seer.issue_summary import get_issue_summary_cache_key
2589+
2590+
self.project.update_option("sentry:seer_scanner_automation", True)
2591+
event = self.create_event(
2592+
data={"message": "testing"},
2593+
project_id=self.project.id,
2594+
)
2595+
2596+
# Set seer_fixability_score on the group
2597+
group = event.group
2598+
group.seer_fixability_score = 0.75
2599+
group.save()
2600+
2601+
# Set cached issue summary
2602+
cache_key = get_issue_summary_cache_key(group.id)
2603+
cache.set(cache_key, {"summary": "test summary"}, 3600)
2604+
2605+
self.call_post_process_group(
2606+
is_new=False, # Not a new group
2607+
is_regression=False,
2608+
is_new_group_environment=False,
2609+
event=event,
2610+
)
2611+
2612+
mock_start_seer_automation.assert_not_called()
2613+
2614+
@patch(
2615+
"sentry.seer.seer_setup.get_seer_org_acknowledgement",
2616+
return_value=True,
2617+
)
2618+
@patch("sentry.tasks.autofix.start_seer_automation.delay")
2619+
@with_feature("organizations:gen-ai-features")
2620+
@with_feature("organizations:trigger-autofix-on-issue-summary")
2621+
def test_kick_off_seer_automation_runs_with_missing_fixability_score(
2622+
self, mock_start_seer_automation, mock_get_seer_org_acknowledgement
2623+
):
2624+
from sentry.seer.issue_summary import get_issue_summary_cache_key
2625+
2626+
self.project.update_option("sentry:seer_scanner_automation", True)
2627+
event = self.create_event(
2628+
data={"message": "testing"},
2629+
project_id=self.project.id,
2630+
)
2631+
2632+
# Group has no seer_fixability_score (None by default)
2633+
group = event.group
2634+
assert group.seer_fixability_score is None
2635+
2636+
# Set cached issue summary
2637+
cache_key = get_issue_summary_cache_key(group.id)
2638+
cache.set(cache_key, {"summary": "test summary"}, 3600)
2639+
2640+
self.call_post_process_group(
2641+
is_new=False, # Not a new group
2642+
is_regression=False,
2643+
is_new_group_environment=False,
2644+
event=event,
2645+
)
2646+
2647+
mock_start_seer_automation.assert_called_once_with(group.id)
2648+
2649+
@patch(
2650+
"sentry.seer.seer_setup.get_seer_org_acknowledgement",
2651+
return_value=True,
2652+
)
2653+
@patch("sentry.tasks.autofix.start_seer_automation.delay")
2654+
@with_feature("organizations:gen-ai-features")
2655+
@with_feature("organizations:trigger-autofix-on-issue-summary")
2656+
def test_kick_off_seer_automation_runs_with_missing_summary_cache(
2657+
self, mock_start_seer_automation, mock_get_seer_org_acknowledgement
2658+
):
2659+
from sentry.seer.issue_summary import get_issue_summary_cache_key
2660+
2661+
self.project.update_option("sentry:seer_scanner_automation", True)
2662+
event = self.create_event(
2663+
data={"message": "testing"},
2664+
project_id=self.project.id,
2665+
)
2666+
2667+
# Set seer_fixability_score on the group
2668+
group = event.group
2669+
group.seer_fixability_score = 0.75
2670+
group.save()
2671+
2672+
# No cached issue summary (cache.get will return None)
2673+
cache_key = get_issue_summary_cache_key(group.id)
2674+
assert cache.get(cache_key) is None
2675+
2676+
self.call_post_process_group(
2677+
is_new=False, # Not a new group
2678+
is_regression=False,
2679+
is_new_group_environment=False,
2680+
event=event,
2681+
)
2682+
2683+
mock_start_seer_automation.assert_called_once_with(group.id)
2684+
25782685

25792686
class PostProcessGroupErrorTest(
25802687
TestCase,

0 commit comments

Comments
 (0)