Skip to content

feat(GAL): Add reset_and_backfill task for group action log#119355

Merged
yuvmen merged 3 commits into
masterfrom
yuvmen/reset-and-backfill-group-action-log
Jul 10, 2026
Merged

feat(GAL): Add reset_and_backfill task for group action log#119355
yuvmen merged 3 commits into
masterfrom
yuvmen/reset-and-backfill-group-action-log

Conversation

@yuvmen

@yuvmen yuvmen commented Jul 9, 2026

Copy link
Copy Markdown
Member

Summary

  • Add reset_and_backfill_group_action_log(group_id) task that clears previously backfilled entries and re-runs the backfill for a single group
  • Only deletes entries with source="backfill:activity" — preserves live-written entries (from web, API, MCP, etc.)
  • Invalidates derived data so it rebuilds from scratch after re-backfill
  • Delegates to the existing backfill_group_action_log_for_group task

Use case

When the translator logic changes or a backfill produced incorrect data, this provides a clean "redo" without losing real-time action log entries.

Test plan

  • Deletes backfilled entries and re-triggers backfill task
  • Preserves non-backfill entries (e.g. source="web")
  • Noop for nonexistent group

Add a task that clears backfilled GroupActionLogEntry rows
(source="backfill:activity") for a group, invalidates derived data,
and re-triggers the single-group backfill. Preserves live-written
entries.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
@yuvmen yuvmen requested a review from a team as a code owner July 9, 2026 21:42
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jul 9, 2026
Comment thread src/sentry/tasks/backfill_group_action_log.py
Comment thread src/sentry/tasks/backfill_group_action_log.py
Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Comment thread src/sentry/tasks/backfill_group_action_log.py
)
return

invalidate_group_derived_data(group_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: A race condition exists where process_group_log_task can run on an empty action log because it's scheduled before the backfill task that populates the log completes.
Severity: HIGH

Suggested Fix

The order of operations should be changed. First, delete the old GroupActionLogEntry entries. Then, schedule the backfill_group_action_log_for_group task. The call to invalidate_group_derived_data should be removed from this function, as the backfill process itself handles invalidation correctly with a cursor, which avoids the race condition.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/sentry/tasks/backfill_group_action_log.py#L74

Potential issue: The function `reset_and_backfill_group_action_log` calls
`invalidate_group_derived_data(group_id)` without a cursor. This immediately deletes the
`GroupDerivedData` row and schedules `process_group_log_task` to run asynchronously.
Subsequently, old log entries are deleted, and a new backfill task is scheduled. A race
condition exists where `process_group_log_task` can execute before the backfill task has
inserted the new data. This would cause the derived data to be rebuilt from an empty or
incomplete action log, leading to incorrect state. The backfilled entries would then be
added without triggering another reprocessing.

invalidate_group_derived_data() also triggers
process_group_log_task which would reprocess stale data. Delete
GroupDerivedData row directly instead — the backfill will rebuild
derived state naturally when it runs.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b9bc2ef. Configure here.

},
)

backfill_group_action_log_for_group.delay(group_id=group_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Derived data not rebuilt

High Severity

reset_and_backfill_group_action_log deletes the group’s GroupDerivedData row, then only enqueues backfill_group_action_log_for_group. That backfill path calls invalidate_group_derived_data with a cursor, which schedules process_group_log_task only when it deletes an existing derived row. With no row left after reset, re-inserted backfill entries may never trigger derived recomputation, leaving derived state missing or stale despite the reset’s stated rebuild goal.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b9bc2ef. Configure here.

)
return

GroupDerivedData.objects.filter(group_id=group_id).delete()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The reset_and_backfill_group_action_log task pre-emptively deletes GroupDerivedData, which prevents the subsequent async backfill from triggering the necessary derived data rebuild task.
Severity: HIGH

Suggested Fix

Remove the initial GroupDerivedData.objects.filter(group_id=group_id).delete() call from the reset_and_backfill_group_action_log task. The existing logic within the async backfill process, specifically the call to invalidate_group_derived_data, should be sufficient to handle the deletion and subsequent reprocessing trigger. This ensures the condition for scheduling the rebuild task is met correctly.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/sentry/tasks/backfill_group_action_log.py#L74

Potential issue: The `reset_and_backfill_group_action_log` task at line 74
unconditionally deletes `GroupDerivedData` records before scheduling an asynchronous
backfill. The backfill process later calls `invalidate_group_derived_data`, which is
supposed to trigger a data rebuild by calling `process_group_log_task.delay()`. However,
this trigger is conditional on `invalidate_group_derived_data` deleting at least one
row. Since the data was already deleted, this condition is never met. As a result, the
derived data is not rebuilt after the backfill completes, leaving it in an unprocessed
state indefinitely, which defeats the purpose of the backfill task.

@yuvmen

yuvmen commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

The bots comment on something I think might be okay - like that the derived state in this case wont be calculated as part of the backfill, but it will lazily get recreated anyway. Guess I could add a manual triggering for process_group_log_task at the end of the backfill_task to force it, but it I am not sure its needed

@yuvmen yuvmen merged commit 0e2f75b into master Jul 10, 2026
65 checks passed
@yuvmen yuvmen deleted the yuvmen/reset-and-backfill-group-action-log branch July 10, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants