-
Notifications
You must be signed in to change notification settings - Fork 0
Organize kick off automation #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1620,17 +1620,10 @@ def check_if_flags_sent(job: PostProcessJob) -> None: | |
| set_project_flag_and_signal(project, "has_flags", first_flag_received) | ||
|
|
||
|
|
||
| def kick_off_seer_automation(job: PostProcessJob) -> None: | ||
| from sentry.seer.autofix.issue_summary import get_issue_summary_lock_key | ||
| def seer_automation_permission_and_type_check(group: Group) -> bool: | ||
| from sentry import quotas | ||
| from sentry.constants import DataCategory | ||
| from sentry.seer.seer_setup import get_seer_org_acknowledgement | ||
| from sentry.tasks.autofix import start_seer_automation | ||
|
|
||
| event = job["event"] | ||
| group = event.group | ||
|
|
||
| # Only run on issues with no existing scan - TODO: Update condition for triage signals V0 | ||
| if group.seer_fixability_score is not None: | ||
| return | ||
|
|
||
| # check currently supported issue categories for Seer | ||
| if group.issue_category not in [ | ||
|
|
@@ -1644,56 +1637,64 @@ def kick_off_seer_automation(job: PostProcessJob) -> None: | |
| GroupCategory.REPLAY, | ||
| GroupCategory.FEEDBACK, | ||
| ]: | ||
| return | ||
| return False | ||
|
|
||
| if not features.has("organizations:gen-ai-features", group.organization): | ||
| return | ||
| return False | ||
|
|
||
| gen_ai_allowed = not group.organization.get_option("sentry:hide_ai_features") | ||
| if not gen_ai_allowed: | ||
| return | ||
| return False | ||
|
|
||
| project = group.project | ||
| if ( | ||
| not project.get_option("sentry:seer_scanner_automation") | ||
| and not group.issue_type.always_trigger_seer_automation | ||
| ): | ||
| return | ||
|
|
||
| # Check if automation has already been queued or completed for this group | ||
| # seer_autofix_last_triggered is set when trigger_autofix is successfully started. | ||
| # Use cache with short TTL to hold lock for a short since it takes a few minutes to set seer_autofix_last_triggeredes | ||
| cache_key = f"seer_automation_queued:{group.id}" | ||
| if cache.get(cache_key) or group.seer_autofix_last_triggered is not None: | ||
| return | ||
|
|
||
| # Don't run if there's already a task in progress for this issue | ||
| lock_key, lock_name = get_issue_summary_lock_key(group.id) | ||
| lock = locks.get(lock_key, duration=1, name=lock_name) | ||
| if lock.locked(): | ||
| return | ||
| return False | ||
|
|
||
| seer_enabled = get_seer_org_acknowledgement(group.organization) | ||
| if not seer_enabled: | ||
| return | ||
|
|
||
| from sentry import quotas | ||
| from sentry.constants import DataCategory | ||
| return False | ||
|
|
||
| has_budget: bool = quotas.backend.has_available_reserved_budget( | ||
| org_id=group.organization.id, data_category=DataCategory.SEER_SCANNER | ||
| ) | ||
| if not has_budget: | ||
| return | ||
| return False | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| def seer_automation_rate_limit_check(group: Group) -> bool: | ||
| from sentry.seer.autofix.utils import is_seer_scanner_rate_limited | ||
|
|
||
| if is_seer_scanner_rate_limited(project, group.organization): | ||
| if is_seer_scanner_rate_limited(group.project, group.organization): | ||
| return False | ||
| return True | ||
|
|
||
|
|
||
| def kick_off_seer_automation(job: PostProcessJob) -> None: | ||
| from sentry.seer.autofix.issue_summary import get_issue_summary_lock_key | ||
| from sentry.tasks.autofix import start_seer_automation | ||
|
|
||
| event = job["event"] | ||
| group = event.group | ||
|
|
||
| # Only run on issues with no existing scan - TODO: Update condition for triage signals V0 | ||
| if group.seer_fixability_score is not None: | ||
| return | ||
|
|
||
| if seer_automation_permission_and_type_check(group) is False: | ||
| return | ||
|
|
||
| # Don't run if there's already a task in progress for this issue | ||
| lock_key, lock_name = get_issue_summary_lock_key(group.id) | ||
| lock = locks.get(lock_key, duration=1, name=lock_name) | ||
| if lock.locked(): | ||
| return | ||
|
|
||
| # cache.add uses Redis SETNX which atomically sets the key only if it doesn't exist | ||
| # Returns False if another process already set the key, ensuring only one process proceeds | ||
| if not cache.add(cache_key, True, timeout=600): # 10 minute | ||
| if seer_automation_rate_limit_check(group) is False: | ||
| return | ||
|
|
||
| start_seer_automation.delay(group.id) | ||
|
Comment on lines
+1677
to
1700
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [CriticalError] Critical: The removal of the cache-based deduplication mechanism (lines checking The old code used The lock check on line 1693-1695 only prevents concurrent execution of this function, but doesn't prevent the same group from being queued multiple times if this function completes and is called again before the async task starts. Consider: Was this deduplication moved elsewhere, or is the Context for Agents |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[BestPractice]
The comparison
is Falseis used here and on line 1697. While technically correct, it's more Pythonic to usenot seer_automation_permission_and_type_check(group)andnot seer_automation_rate_limit_check(group)since these functions return boolean values, not None/False ambiguity.Suggestion:
Context for Agents