Skip to content

chore(alerts): Clean up old metric alert rows in NotificationMessage#115647

Merged
ceorourke merged 6 commits into
masterfrom
ceorourke/clean-notificationmessage
May 15, 2026
Merged

chore(alerts): Clean up old metric alert rows in NotificationMessage#115647
ceorourke merged 6 commits into
masterfrom
ceorourke/clean-notificationmessage

Conversation

@ceorourke
Copy link
Copy Markdown
Member

We have not written metric alert rows (those with incident and trigger_action) since October of last year and only read the workflow engine rows (those with action and group). To prep for removing the metric alert rows and making the workflow engine ones not nullable, we must first clean up all the old rows.

@ceorourke ceorourke requested review from a team as code owners May 15, 2026 16:47
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 15, 2026
Comment thread src/sentry/notifications/migrations/0009_clean_old_notificationmessage.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

This PR has a migration; here is the generated SQL for src/sentry/notifications/migrations/0009_clean_old_notificationmessage.py

for 0009_clean_old_notificationmessage in notifications

--
-- Raw Python operation
--
-- THIS OPERATION CANNOT BE WRITTEN AS SQL

Copy link
Copy Markdown
Member

@wedamija wedamija left a comment

Choose a reason for hiding this comment

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

lgtm, most recent row with these columns null is from 2025-10-08 21:19

Comment on lines +14 to +17
for row in RangeQuerySetWrapperWithProgressBar(
NotificationMessage.objects.filter(incident__isnull=False, trigger_action__isnull=False)
):
row.delete()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will hopefully work ok, something using RangeQuerySetWrapperWithProgressBar can fail due to there not being an explicit index on incident, trigger_action, id.

Btw, I noticed that we never expire data from this table. Should we be doing that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Probably yes, this table is massive and only used for threading message replies in Slack. I can look into getting that set up.

Copy link
Copy Markdown
Member Author

@ceorourke ceorourke May 15, 2026

Choose a reason for hiding this comment

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

@wedamija Is there something else I can use besides RangeQuerySetWrapperWithProgressBar? The test I added keeps failing because it's too slow so I'm worried about timeouts when I actually apply this. Maybe I should batch the deletes?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I doubt that's the reason the test is failing... There aren't that many rows in the table afaik. Does it pass locally? It could also just be worth a retry

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah it passes locally, I'll retry it again.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Probably yes, this table is massive and only used for threading message replies in Slack. I can look into getting that set up.

To do that we'll need to add an index on date_added, or whatever we should use to ttl these out. I'm not sure if there's any reason we don't do this already... Like if we need a reference to old notification messages for any reason?

Comment on lines +35 to +36
dependencies = [
("notifications", "0008_remove_metric_alert_constraints_notificationmessage"),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder if the reason the test is slow is something to do with the dependencies. Maybe we should make sure this depends on the latest sentry migration too? Just a random guess...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Trying that now, if it still fails I'll try a batched approach

Copy link
Copy Markdown
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 is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cc8fba7. Configure here.

for row in RangeQuerySetWrapperWithProgressBar(
NotificationMessage.objects.filter(incident__isnull=False, trigger_action__isnull=False)
):
row.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.

Row-by-row deletion on massive table causes extreme slowness

High Severity

The migration deletes rows one at a time via row.delete() inside a RangeQuerySetWrapperWithProgressBar loop. On a table described as "massive," this issues a separate SQL DELETE statement per row, which is extremely slow and risks timeouts. The codebase already provides bulk_delete_objects in sentry.utils.query that efficiently batch-deletes using subquery-based DELETE ... WHERE id IN (SELECT ...). A batched approach would reduce millions of individual queries to a manageable number of batch operations.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cc8fba7. Configure here.

@github-actions
Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on 84853d1 in this run:

tests/sentry/sentry_apps/tasks/test_sentry_apps.py::TestDisabledSentryAppWebhooks::test_send_metric_alert_webhook_blocked_for_disabled_applog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140709638843264_x9749"
tests/sentry/sentry_apps/tasks/test_sentry_apps.py::TestDisabledSentryAppWebhooks::test_workflow_notification_blocked_for_disabled_applog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:404: in _pre_setup
    super()._pre_setup()
src/sentry/utils/db.py:64: in _enter
    return original_enter(self)
           ^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/transaction.py:211: in __enter__
    sid = connection.savepoint()
          ^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/asyncio.py:26: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:400: in savepoint
    self._savepoint(sid)
.venv/lib/python3.13/site-packages/django/db/backends/base/base.py:367: in _savepoint
    cursor.execute(self.ops.savepoint_create_sql(sid))
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'default'}, but command running against db control
E   SQL: SAVEPOINT "s140709638843264_x9755"
tests/sentry/snuba/test_discover_timeseries_query.py::DiscoverTimeseriesQueryTest::test_comparison_aggregate_function_invalidlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/snuba/test_discover_timeseries_query.py:32: in setUp
    project_id=self.project.id,
               ^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/functional.py:47: in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/fixtures.py:122: in project
    return self.create_project(name="Bar", slug="bar", teams=[self.team])
                                                              ^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/functional.py:47: in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/contextlib.py:85: in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/fixtures.py:113: in team
    team = self.create_team(organization=self.organization, name="foo", slug="foo")
                                         ^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/functional.py:47: in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/fixtures.py:108: in organization
    return self.create_organization(name="baz", slug="baz", owner=self.user)
                                                                  ^^^^^^^^^
.venv/lib/python3.13/site-packages/django/utils/functional.py:47: in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/fixtures.py:94: in user
    return self.create_user(
src/sentry/testutils/fixtures.py:313: in create_user
    return Factories.create_user(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/contextlib.py:85: in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/factories.py:1102: in create_user
    user.save(is_test_user=is_test_user)
src/sentry/silo/base.py:157: in override
    return original_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/users/models/user.py:244: in save
    with outbox_context(transaction.atomic(using=router.db_for_write(User))):
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/opt/hostedtoolcache/Python/3.13.1/x64/lib/python3.13/contextlib.py:141: in __enter__
    return next(self.gen)
           ^^^^^^^^^^^^^^
src/sentry/hybridcloud/models/outbox.py:552: in outbox_context
    with unguarded_write(using=inner.using), enforce_constraints(inner):
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
... (26 more lines)
tests/sentry/synapse/endpoints/test_org_cell_mappings.py::OrgCellMappingsTest::test_get_no_authlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:411: in _post_teardown
    super()._post_teardown()
.venv/lib/python3.13/site-packages/django/db/backends/postgresql/base.py:482: in check_constraints
    cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'secondary'}, but command running against db control
E   SQL: SET CONSTRAINTS ALL IMMEDIATE
tests/sentry/synapse/test_paginator.py::CursorTest::test_encode_decodelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:411: in _post_teardown
    super()._post_teardown()
.venv/lib/python3.13/site-packages/django/db/backends/postgresql/base.py:482: in check_constraints
    cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'secondary'}, but command running against db control
E   SQL: SET CONSTRAINTS ALL IMMEDIATE
tests/sentry/tasks/test_ai_agent_monitoring.py::FetchAIModelMetadataTest::test_create_prefix_glob_model_namelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:411: in _post_teardown
    super()._post_teardown()
.venv/lib/python3.13/site-packages/django/db/backends/postgresql/base.py:482: in check_constraints
    cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'secondary'}, but command running against db control
E   SQL: SET CONSTRAINTS ALL IMMEDIATE
tests/sentry/utils/test_http.py::OriginFromRequestTestCase::test_nothinglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:411: in _post_teardown
    super()._post_teardown()
.venv/lib/python3.13/site-packages/django/db/backends/postgresql/base.py:482: in check_constraints
    cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'secondary'}, but command running against db control
E   SQL: SET CONSTRAINTS ALL IMMEDIATE
tests/sentry/workflow_engine/receivers/test_project_detectors.py::TestDisableDefaultDetectorCreation::test_context_manager_reconnects_on_exceptionlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:411: in _post_teardown
    super()._post_teardown()
.venv/lib/python3.13/site-packages/django/db/backends/postgresql/base.py:482: in check_constraints
    cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'secondary'}, but command running against db control
E   SQL: SET CONSTRAINTS ALL IMMEDIATE
tests/sentry_plugins/test_client.py::ApiClientTest::test_postlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
src/sentry/testutils/cases.py:411: in _post_teardown
    super()._post_teardown()
.venv/lib/python3.13/site-packages/django/db/backends/postgresql/base.py:482: in check_constraints
    cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:122: in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/sentry_sdk/utils.py:1887: in runner
    return original_function(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:79: in execute
    return self._execute_with_wrappers(
.venv/lib/python3.13/site-packages/django/db/backends/utils.py:92: in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:70: in _execute__include_sql_in_error
    return execute(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/db/postgres/base.py:58: in _execute__clean_params
    return execute(sql, clean_bad_params(params), many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/sentry/testutils/hybrid_cloud.py:129: in __call__
    raise CrossTransactionAssertionError(
E   sentry.testutils.hybrid_cloud.CrossTransactionAssertionError: Transaction opened for db {'secondary'}, but command running against db control
E   SQL: SET CONSTRAINTS ALL IMMEDIATE

@ceorourke ceorourke merged commit 09fdffc into master May 15, 2026
115 of 118 checks passed
@ceorourke ceorourke deleted the ceorourke/clean-notificationmessage branch May 15, 2026 19:39
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.

3 participants