Skip to content

Conversation

@cathteng
Copy link
Member

Add an outbox to update actions statuses when a sentry app installation is deleted. This will be eventually consistent.

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Oct 21, 2025
@codecov
Copy link

codecov bot commented Oct 21, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
41275 1 41274 251
View the top 1 failed test(s) by shortest run time
tests.sentry.deletions.test_sentry_app_installations.TestSentryAppInstallationDeletionTask::test_disables_actions
Stack Traces | 3.74s run time
#x1B[1m#x1B[.../sentry/deletions/test_sentry_app_installations.py#x1B[0m:134: in test_disables_actions
    assert action.status == ObjectStatus.DISABLED
#x1B[1m#x1B[31mE   AssertionError: assert 0 == 1#x1B[0m
#x1B[1m#x1B[31mE    +  where 0 = <Action at 0x7f24545e5910: id=13, type='sentry_app'>.status#x1B[0m
#x1B[1m#x1B[31mE    +  and   1 = ObjectStatus.DISABLED#x1B[0m

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Base automatically changed from cathy/eco/unstuck-sentry-app-install-deletion to master October 21, 2025 23:25
Comment on lines 145 to 160
return [
ControlOutbox(
shard_scope=OutboxScope.APP_SCOPE,
shard_identifier=self.id,
object_identifier=self.id,
category=OutboxCategory.SENTRY_APP_INSTALLATION_DELETE,
region_name=region_name,
payload={"uuid": self.uuid},
)
for region_name in find_all_region_names()
Copy link
Member

Choose a reason for hiding this comment

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

Changes look good, just needs testing

Copy link
Member

Choose a reason for hiding this comment

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

Oh does this still need a new delete override on SentryAppInstallation as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes I found out while testing lmao

@cathteng cathteng marked this pull request as ready for review October 21, 2025 23:37
@cathteng cathteng requested review from a team as code owners October 21, 2025 23:37
Comment on lines 128 to 132
with outbox_context(transaction.atomic(using=router.db_for_write(SentryAppInstallation))):
for outbox in self.outboxes_for_delete():
outbox.save()
return super().delete(*args, **kwargs)

Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: The SentryAppInstallation.delete() override calls super().delete() outside its transaction, creating a race condition between the creation of deletion outboxes and the actual model deletion.
(Severity: High 0.80 | Confidence: 0.95)

🔍 Detailed Analysis

The override of SentryAppInstallation.delete() creates and saves deletion outboxes within one transaction but calls super().delete() outside of it. This parent method call initiates a second, separate transaction to perform the soft-delete and create its own update outboxes. This creates a race condition where the deletion outboxes can be processed by the receiver before the model is actually soft-deleted. This can lead to inconsistent states, such as actions being disabled for an installation that has not yet been marked as deleted in the database.

💡 Suggested Fix

Move the super().delete(*args, **kwargs) call inside the with outbox_context(...) block. This ensures that the creation of deletion outboxes and the execution of the parent's delete logic occur within the same atomic transaction, preventing race conditions.

🤖 Prompt for AI Agent
Fix this bug. In src/sentry/sentry_apps/models/sentry_app_installation.py at lines
128-132: The override of `SentryAppInstallation.delete()` creates and saves deletion
outboxes within one transaction but calls `super().delete()` outside of it. This parent
method call initiates a second, separate transaction to perform the soft-delete and
create its own update outboxes. This creates a race condition where the deletion
outboxes can be processed by the receiver before the model is actually soft-deleted.
This can lead to inconsistent states, such as actions being disabled for an installation
that has not yet been marked as deleted in the database.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Member Author

Choose a reason for hiding this comment

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

what this is fine

@cathteng cathteng force-pushed the cathy/eco/sentry-app-install-delete-outbox branch from 455ff76 to 1d88eb1 Compare October 21, 2025 23:41
cursor[bot]

This comment was marked as outdated.

return [
ControlOutbox(
shard_scope=OutboxScope.APP_SCOPE,
shard_identifier=self.id,
Copy link
Member

Choose a reason for hiding this comment

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

Can we use the same shard_identifier as update? Having the same sharding keys ensures that all the outboxes for a specific record are processed in order.

payload={"uuid": self.uuid},
)
for region_name in find_all_region_names()
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Bug: Inconsistent Region Targeting in Delete Method

The SentryAppInstallation.delete method's outboxes_for_delete targets all regions, unlike outboxes_for_update which correctly targets only regions where the organization exists. This inconsistency sends unnecessary delete messages to irrelevant regions, potentially causing processing errors or breaking replication ordering.

Fix in Cursor Fix in Web

Copy link
Member Author

@cathteng cathteng Oct 28, 2025

Choose a reason for hiding this comment

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

The organization might already be deleted by the time we get here in the sentry app / install deletion task. See #101895

@cathteng cathteng merged commit aad8c49 into master Oct 28, 2025
69 checks passed
@cathteng cathteng deleted the cathy/eco/sentry-app-install-delete-outbox branch October 28, 2025 17:49
@sentry
Copy link

sentry bot commented Oct 31, 2025

Issues attributed to commits in this pull request

This pull request was merged and Sentry observed the following issues:

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.

4 participants