Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/sentry/api/endpoints/debug_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,11 +858,15 @@ def _clone_proguard_debug_file_for_reupload(
}

meta = build_proguard_reupload_dif_meta(debug_file, requested_debug_id)
if not debug_file.uses_objectstore_for_read():
if debug_file.storage_path is None:
assert debug_file.file is not None
dif, created = create_dif_from_id(project, meta, file=debug_file.file)
else:
source_fileobj = debug_file.get_file()
response = debug_file._get_objectstore_session().get(debug_file.storage_path)
if response is None:
raise FileNotFoundError("Debug file does not exist in Objectstore")
Comment thread
lcian marked this conversation as resolved.

source_fileobj = response.payload
try:
# Spool into a temporary file to get a seekable stream.
with tempfile.TemporaryFile() as tmp:
Expand Down
86 changes: 86 additions & 0 deletions tests/sentry/api/endpoints/test_dif_assemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,59 @@ def test_reuses_existing_proguard_file_with_new_debug_id(self) -> None:
assert first_dif.file_id == second_dif.file_id
assert File.objects.filter(type="project.dif", checksum=checksum).count() == 1

def test_objectstore_assemble_clones_existing_proguard_to_new_objectstore_file(self) -> None:
file_contents = b"proguard mapping"
checksum = sha1(file_contents).hexdigest()
get_chunk_upload_session(self.organization.id).put(file_contents, key=checksum)
chunks = [checksum]

with self.feature(
{
"organizations:objectstore-debugfiles-exclusive-write": True,
"organizations:objectstore-debugfiles-write": False,
"organizations:objectstore-debugfiles-read": True,
}
):
assemble_dif(
project_id=self.project.id,
name="/proguard/mapping-00000000-0000-0000-0000-000000000000.txt",
checksum=checksum,
chunks=chunks,
use_objectstore=True,
)

first_dif = ProjectDebugFile.objects.get(
project_id=self.project.id,
debug_id="00000000-0000-0000-0000-000000000000",
)

response = self.client.post(
self.url,
data={
checksum: {
"name": "/proguard/mapping-11111111-1111-1111-1111-111111111111.txt",
"chunks": chunks,
}
},
HTTP_AUTHORIZATION=f"Bearer {self.token.token}",
)

assert response.status_code == 200, response.content
assert response.data[checksum]["state"] == ChunkFileState.OK
assert response.data[checksum]["dif"]["uuid"] == "11111111-1111-1111-1111-111111111111"

second_dif = ProjectDebugFile.objects.get(
project_id=self.project.id,
debug_id="11111111-1111-1111-1111-111111111111",
)

assert first_dif.file_id is None
assert second_dif.file_id is None
assert first_dif.storage_path is not None
assert second_dif.storage_path is not None
assert first_dif.storage_path != second_dif.storage_path
assert File.objects.filter(type="project.dif", checksum=checksum).count() == 0

def test_reupload_proguard_with_same_debug_id_is_idempotent(self) -> None:
file_contents = b"proguard mapping"
checksum = sha1(file_contents).hexdigest()
Expand Down Expand Up @@ -590,6 +643,7 @@ def test_clone_dual_written_source_to_file(self) -> None:
)
assert first_dif.file_id is not None
assert first_dif.storage_path is not None
assert not first_dif.uses_objectstore_for_read()

with self.feature({"organizations:objectstore-debugfiles-write": False}):
response = self._clone_request(checksum, chunks)
Expand All @@ -604,5 +658,37 @@ def test_clone_dual_written_source_to_file(self) -> None:
)
# The source stays Objectstore-backed; the clone is written as a File.
assert second_dif.file_id is not None
assert second_dif.file_id != first_dif.file_id
assert second_dif.storage_path is None
assert second_dif.get_file().read() == file_contents

def test_clone_file_backed_source_to_objectstore_exclusive(self) -> None:
file_contents = b"proguard mapping"
checksum = sha1(file_contents).hexdigest()
blob = FileBlob.from_file_with_organization(ContentFile(file_contents), self.organization)
chunks = [blob.checksum]

with self.feature({"organizations:objectstore-debugfiles-write": False}):
self._assemble_source(checksum, chunks)

first_dif = ProjectDebugFile.objects.get(
project_id=self.project.id,
debug_id="00000000-0000-0000-0000-000000000000",
)
assert first_dif.file_id is not None
assert first_dif.storage_path is None

with self.feature("organizations:objectstore-debugfiles-exclusive-write"):
response = self._clone_request(checksum, chunks)

assert response.status_code == 200, response.content
assert response.data[checksum]["state"] == ChunkFileState.OK

second_dif = ProjectDebugFile.objects.get(
project_id=self.project.id,
debug_id="11111111-1111-1111-1111-111111111111",
)
assert second_dif.file_id is None
assert second_dif.storage_path is not None
assert second_dif.get_file().read() == file_contents
assert File.objects.filter(type="project.dif", checksum=checksum).count() == 1
Loading