Skip to content

feat(relocation) Use a shared bucket for relocations#116108

Open
markstory wants to merge 11 commits into
masterfrom
feat-relocation-no-blob-move
Open

feat(relocation) Use a shared bucket for relocations#116108
markstory wants to merge 11 commits into
masterfrom
feat-relocation-no-blob-move

Conversation

@markstory
Copy link
Copy Markdown
Member

We've had a number of problems with relocations timing out or consuming too much memory as export files are moved between control + cells. The RPC calls and file operations would be much simpler if there was only a single shared bucket, instead of one bucket per-cell. Futhermore, I've removed all the of the file copying which should improve performance and reliability.

We've already provisioned a new shared bucket and configuration changes to use that bucket are in getsentry/ops#20737

There is still some cleanup work to be done and I've added some TODOs for what I plan to address in the short term.

Refs INFRENG-318

markstory added 11 commits May 22, 2026 19:43
There were more file moves :| Instead of copying all that data around
lets put the upload/export in the right place to start with. Now that we
have a shared bucket there is no reason to move files around.
With a shared bucket we don't need ot shuffle files around nearly as
much. This should address both the slow RPC durations as well as the
overall performance of relocations.
Transfer operations don't touch relocation blobs anymore.
The storage backend caches file contents and this cost me an hour of
debugging.
@markstory markstory requested a review from a team as a code owner May 22, 2026 23:51
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 22, 2026

INFRENG-318

@markstory markstory requested a review from a team May 22, 2026 23:51
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 22, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Backend Test Failures

Failures on d6ecdaa in this run:

tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_expired_superuser_when_feature_disabledlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_file_not_foundlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_owner_has_another_active_relocationlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_relocation_file_not_foundlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_relocation_not_foundlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_relocation_still_ongoinglog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_staff_owner_not_foundlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_superuser_owner_not_foundlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_throttledlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_bad_without_staff_when_feature_disabledlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_good_simplelog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_good_staff_when_feature_disabledlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'
tests/sentry/relocation/api/endpoints/test_retry.py::RetryRelocationTest::test_good_superuser_when_feature_disabledlog
[gw1] linux -- Python 3.13.1 /home/runner/work/sentry/sentry/.venv/bin/python3
tests/sentry/relocation/api/endpoints/test_retry.py:81: in setUp
    bucket_path=RelocationFile.Kind.RAW_USER_DATA.bucket_path(self.relocation.uuid, "tar"),
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E   AttributeError: 'Kind' object has no attribute 'bucket_path'

# was stored in the shared bucket, create a RelocationFile record
# so that the import process can begin.
# TODO(cells) Remove this once RelocationFile.file is optional.
file = File.objects.create(name="stub", type=RELOCATION_FILE_TYPE, size=10000)
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 stub File for SAAS-to-SAAS relocations is created with a hardcoded size=10000, causing all such relocations to be miscategorized as "small" for throttling purposes.
Severity: MEDIUM

Suggested Fix

Instead of creating a stub File with a hardcoded size, the actual size of the relocation export should be determined and stored. This will ensure the should_throttle_relocation function correctly categorizes relocations and applies the throttling limits as intended.

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/relocation/services/relocation_export/impl.py#L112

Potential issue: For SAAS-to-SAAS relocations, a stub `File` object is created with a
hardcoded `size=10000`. The throttling logic in `should_throttle_relocation` uses this
size to categorize relocations. Consequently, all SAAS-to-SAAS relocations, regardless
of their actual size, are classified as "small". This skews the throttling counts, as
large relocations are not counted against the "medium" or "large" limits. This could
lead to bypassing the daily quota for large self-hosted relocations, as previous large
SAAS-to-SAAS relocations no longer contribute to the limit.

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

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 0ececbc. Configure here.

)
RelocationFile.objects.create(
relocation=new_relocation,
file=file,
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.

Retry flow breaks due to mismatched bucket path

High Severity

When retrying a relocation, the new RelocationFile copies bucket_path from the old relocation (e.g. runs/{old_uuid}/in/raw-relocation-data.tar), but the new relocation gets a different UUID. The old preprocessing_transfer code used to copy the raw data file from Django's filestore into runs/{new_uuid}/in/, but that copy step was removed in this PR. Now preprocessing_complete checks runs/{new_uuid}/in/raw-relocation-data.tar and Cloud Build copies from runs/{new_uuid}/in/ — but the file only exists at the old UUID's path. Retried relocations will always fail with a FileNotFoundError.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0ececbc. Configure here.

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.

1 participant