Skip to content

ref(db): Migrate create_or_update to update_or_create#111510

Merged
vgrozdanic merged 2 commits intomasterfrom
vgrozdanic/ref/migrate-create-or-update-phase-1d
Mar 25, 2026
Merged

ref(db): Migrate create_or_update to update_or_create#111510
vgrozdanic merged 2 commits intomasterfrom
vgrozdanic/ref/migrate-create-or-update-phase-1d

Conversation

@vgrozdanic
Copy link
Member

@vgrozdanic vgrozdanic commented Mar 25, 2026

Continues the migration away from Sentry's legacy create_or_update helper toward Django's built-in update_or_create.

All three files removed from the allowlist in tests/sentry/test_no_create_or_update_usage.py.

Return values were ignored at all sites, so no caller changes are needed.

Migrate the four remaining phase-1d call sites from the legacy Sentry
create_or_update helper to Django's update_or_create:

- tasks/commits.py: LatestRepoReleaseEnvironment lookup
- tasks/assemble.py: ReleaseArtifactBundle and ProjectArtifactBundle
  (values= and defaults= pointed at the same dict; collapsed to defaults=)
- audit_log/services/log/impl.py: UserIP record
- core/endpoints/organization_details.py: ProjectOption target_sample_rate

Removes these four files from the create_or_update allowlist in
tests/sentry/test_no_create_or_update_usage.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Mar 25, 2026
@vgrozdanic vgrozdanic changed the title ref(db): Migrate create_or_update to update_or_create (phase 1d) ref(db): Migrate create_or_update to update_or_create Mar 25, 2026
@vgrozdanic vgrozdanic marked this pull request as ready for review March 25, 2026 09:25
@vgrozdanic vgrozdanic requested review from a team as code owners March 25, 2026 09:25
Copy link
Contributor

@cursor cursor bot left a comment

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 prepared a fix for the issue found in the latest run.

  • ✅ Fixed: No unique constraint causes MultipleObjectsReturned error
    • Added try-except blocks to catch MultipleObjectsReturned and fall back to filter().update() for backward compatibility with existing duplicate rows.

Create PR

Or push these changes by commenting:

@cursor push 62de5983df
Preview (62de5983df)
diff --git a/src/sentry/tasks/assemble.py b/src/sentry/tasks/assemble.py
--- a/src/sentry/tasks/assemble.py
+++ b/src/sentry/tasks/assemble.py
@@ -426,23 +426,38 @@
 
             # If a release version is passed, we want to create the weak association between a bundle and a release.
             if self.release:
-                ReleaseArtifactBundle.objects.update_or_create(
-                    organization_id=self.organization.id,
-                    release_name=self.release,
-                    # In case no dist is provided, we will fall back to "" which is the NULL equivalent for our
-                    # tables.
-                    dist_name=self.dist or NULL_STRING,
-                    artifact_bundle=artifact_bundle,
-                    defaults=new_date_added,
-                )
+                try:
+                    ReleaseArtifactBundle.objects.update_or_create(
+                        organization_id=self.organization.id,
+                        release_name=self.release,
+                        # In case no dist is provided, we will fall back to "" which is the NULL equivalent for our
+                        # tables.
+                        dist_name=self.dist or NULL_STRING,
+                        artifact_bundle=artifact_bundle,
+                        defaults=new_date_added,
+                    )
+                except ReleaseArtifactBundle.MultipleObjectsReturned:
+                    ReleaseArtifactBundle.objects.filter(
+                        organization_id=self.organization.id,
+                        release_name=self.release,
+                        dist_name=self.dist or NULL_STRING,
+                        artifact_bundle=artifact_bundle,
+                    ).update(**new_date_added)
 
             for project_id in self.project_ids:
-                ProjectArtifactBundle.objects.update_or_create(
-                    organization_id=self.organization.id,
-                    project_id=project_id,
-                    artifact_bundle=artifact_bundle,
-                    defaults=new_date_added,
-                )
+                try:
+                    ProjectArtifactBundle.objects.update_or_create(
+                        organization_id=self.organization.id,
+                        project_id=project_id,
+                        artifact_bundle=artifact_bundle,
+                        defaults=new_date_added,
+                    )
+                except ProjectArtifactBundle.MultipleObjectsReturned:
+                    ProjectArtifactBundle.objects.filter(
+                        organization_id=self.organization.id,
+                        project_id=project_id,
+                        artifact_bundle=artifact_bundle,
+                    ).update(**new_date_added)
 
             # Instead of doing a `create_or_update` one-by-one, we will instead:
             # - Use a `bulk_create` with `ignore_conflicts` to insert new rows efficiently

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

ReleaseArtifactBundle and ProjectArtifactBundle lack unique constraints,
so update_or_create would raise MultipleObjectsReturned on duplicate rows.
Restore create_or_update (filter+update semantics) and keep assemble.py in
the allowlist until unique constraints are added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Member

@jjbayer jjbayer left a comment

Choose a reason for hiding this comment

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

PR description still mentions "four".

@vgrozdanic vgrozdanic merged commit d32591e into master Mar 25, 2026
108 checks passed
@vgrozdanic vgrozdanic deleted the vgrozdanic/ref/migrate-create-or-update-phase-1d branch March 25, 2026 10:51
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