Skip to content

feat(cells): Add post deploy migration to fix OrganizationMapping.date_created field#115406

Closed
lynnagara wants to merge 8 commits into
masterfrom
orgmapping-date-created-backfill
Closed

feat(cells): Add post deploy migration to fix OrganizationMapping.date_created field#115406
lynnagara wants to merge 8 commits into
masterfrom
orgmapping-date-created-backfill

Conversation

@lynnagara
Copy link
Copy Markdown
Member

Context

Follow-up to #115325. That PR made update_organization_mapping_from_instance carry Organization.date_added into OrganizationMapping.date_created going forward, but existing mapping rows still hold whatever timezone.now() was captured at mapping insert time. This migration repairs them.

Implementation

The migration emits one CellOutbox per Organization with category=ORGANIZATION_UPDATE. The standard cell receiver drains each one and re-runs Organization.handle_async_replication, which now plumbs date_addeddate_created through to the mapping.

Roll out notes

This is a post-deploy migration to be triggered manually.

The migration replicates the whole row. The date_updated field will be bumped on every row. Since nothing reads that today (only Synapse will, later), this should be safe.

An increase in memcached set commands are expected during the migration as caches will be updated for each row. Given the number of orgs (relatively small) and the outbox delivery concurrency cap of 5, this volume is trivial for memcached.

Alternative approaches considered

An alternative approach considered was a new temporary, more targeted RPC method that updates only the date_created row and not the rest of the fields. However creating all the throwaway methods, receivers, categories comes with it's own cost and adds additional risk associated with incorrect implementation. It's probably not worth it for a one-shot migration.

…e_created fields

Follow-up to #115325. That PR made `update_organization_mapping_from_instance`
carry `Organization.date_added` into `OrganizationMapping.date_created` going
forward, but existing mapping rows still hold whatever `timezone.now()` was
captured at mapping insert time. This migration repairs them.

The migration emits one `CellOutbox` per `Organization` with
`category=ORGANIZATION_UPDATE`. The standard cell receiver drains each one
and re-runs `Organization.handle_async_replication`, which now plumbs
`date_added` → `date_created` through to the mapping.

This is a post-deploy migration to be triggered manually.

Note: this migration replicates the whole row. `date_updated` wil be bumped on every row.
Nothing reads that today (Synapse will, later).

One alternative appraoch that I considered was a new temporary, more targeted RPC method
that updates only the `date_created` row. I decided to reuse the existing RPC method here
- creating all the throwaway methods, receivers, categories is probably not worth it for a
one-shot migration, and adds additional risk associated with incorrect implementation.
@lynnagara lynnagara requested a review from a team as a code owner May 12, 2026 19:18
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This PR has a migration; here is the generated SQL for src/sentry/migrations/1089_backfill_organization_mapping_date_created.py

for 1089_backfill_organization_mapping_date_created in sentry

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

Comment thread src/sentry/migrations/1089_backfill_organization_mapping_date_created.py Outdated
Comment thread src/sentry/migrations/1089_backfill_organization_mapping_date_created.py Outdated
Comment on lines +40 to +42
for org_id in Organization.objects.values_list("id", flat=True).iterator(
chunk_size=_BATCH_SIZE
):
Copy link
Copy Markdown
Member

@wedamija wedamija May 12, 2026

Choose a reason for hiding this comment

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

I don't completely remember why, but I feel like .iterator doesn't work for us... I think it tries to use server side cursors maybe, which don't work due to pgbouncer

Instead, you can use something like

    for org_id in RangeQuerySetWrapperWithProgressBar(
        Organization.objects.values_list(id", flat=True),
        result_value_getter=lambda values: values[0],
    ):

Copy link
Copy Markdown
Member

@wedamija wedamija May 12, 2026

Choose a reason for hiding this comment

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

Alternatively, there aren't that many orgs. You could just bring the whole set of org ids into memory and iterate over them

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.

Wouldn't using RangeQuerySetWrapperWithProgressBar be a solution we know is going to work?

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.

It's the more standard solution, I just like to give folks options

Copy link
Copy Markdown
Member

@markstory markstory left a comment

Choose a reason for hiding this comment

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

Did you consider using the existing outbox backfill tooling for this? By creating this many outboxes all at once, we are more likely to impact latency for customer operations, and potentially contribute to contention in postgres.

Comment on lines +40 to +42
for org_id in Organization.objects.values_list("id", flat=True).iterator(
chunk_size=_BATCH_SIZE
):
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.

Wouldn't using RangeQuerySetWrapperWithProgressBar be a solution we know is going to work?

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 08b272d. Configure here.

Comment thread tests/sentry/migrations/test_1089_backfill_organization_mapping_date_created.py Outdated
@lynnagara
Copy link
Copy Markdown
Member Author

Did you consider using the existing outbox backfill tooling for this? By creating this many outboxes all at once, we are more likely to impact latency for customer operations, and potentially contribute to contention in postgres.

are you saying incrementing the replication version will take care of everything?
like #115423

@github-actions
Copy link
Copy Markdown
Contributor

This PR has a migration; here is the generated SQL for src/sentry/migrations/1090_backfill_organization_mapping_date_created.py

for 1090_backfill_organization_mapping_date_created in sentry

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

@github-actions
Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on df36ad1 in this run:

tests/sentry/sentry_apps/tasks/test_sentry_apps.py::TestDisabledSentryAppWebhooks::test_send_metric_alert_webhook_blocked_for_disabled_applog
[gw0] 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 "s140717949008768_x9578"
tests/sentry/sentry_apps/tasks/test_sentry_apps.py::TestDisabledSentryAppWebhooks::test_workflow_notification_blocked_for_disabled_applog
[gw0] 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 "s140717949008768_x9584"
tests/sentry/snuba/test_discover_timeseries_query.py::DiscoverTimeseriesQueryTest::test_comparison_aggregate_function_invalidlog
[gw0] 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 "s140717949008768_x9608"
tests/sentry/snuba/test_errors.py::ErrorsQueryIntegrationTest::test_auto_fields_aggregateslog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/snuba/test_errors.py:28: in setUp
    self.environment = self.create_environment(self.project, name="prod")
                                               ^^^^^^^^^^^^
.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:308: 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:1076: 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/snuba/test_errors.py::ErrorsQueryIntegrationTest::test_project_mappinglog
[gw0] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/snuba/test_errors.py:28: in setUp
    self.environment = self.create_environment(self.project, name="prod")
                                               ^^^^^^^^^^^^
.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:308: 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:1076: 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
[gw0] 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
[gw0] 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
[gw0] 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

@wedamija
Copy link
Copy Markdown
Member

Did you consider using the existing outbox backfill tooling for this? By creating this many outboxes all at once, we are more likely to impact latency for customer operations, and potentially contribute to contention in postgres.

I'm not too familiar with this tooling. If we don't need to have this all run on self hosted maybe it makes more sense?

lynnagara added a commit that referenced this pull request May 13, 2026
… date_created (#115423)

Triggers backfill_outboxes.py to re-replicate every Organization
upserting OrganizationMapping.date_created with the value from
Organization.date_added now that #115325 plumbs it through.

Alternative to #115406

Roll out:
- needs to be flipped to 5 in sentry-options-automator to take effect in
production
@lynnagara
Copy link
Copy Markdown
Member Author

superceded by #115423

@lynnagara lynnagara closed this May 13, 2026
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