From e045af469a55741e450713b21938433d5e4c83da Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Mon, 11 May 2026 17:04:44 +0200 Subject: [PATCH 1/4] wip --- relay-server/src/endpoints/common.rs | 35 +++++++++++++++++++++-- relay-server/src/endpoints/minidump.rs | 5 ++-- relay-server/src/endpoints/playstation.rs | 3 +- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/relay-server/src/endpoints/common.rs b/relay-server/src/endpoints/common.rs index df850fd0034..2a2b9147bfa 100644 --- a/relay-server/src/endpoints/common.rs +++ b/relay-server/src/endpoints/common.rs @@ -19,7 +19,7 @@ use crate::envelope::{ AttachmentPlaceholder, AttachmentType, ContentType, Envelope, EnvelopeError, Item, ItemType, Items, }; -use crate::managed::{Managed, Rejected}; +use crate::managed::{Managed, ManagedResult, Rejected}; use crate::service::ServiceState; use crate::services::buffer::{ProjectKeyPair, PushError}; use crate::services::outcome::{DiscardItemType, DiscardReason, Outcome}; @@ -543,7 +543,36 @@ pub async fn upload_to_objectstore( scoping: Scoping, upload: &Addr, referrer: &'static str, -) -> Option> +) -> Result, Rejected<()>> +where + S: futures::Stream> + Send + 'static, + E: Into> + 'static, +{ + let res = upload_to_objectstore_inner( + stream, + content_type, + &mut item, + config, + scoping, + upload, + referrer, + ) + .await; + match res { + Some(()) => Ok(item), + None => Err(Outcome::Invalid(DiscardReason::Internal)).reject(&item), + } +} + +async fn upload_to_objectstore_inner( + stream: S, + content_type: Option, + item: &mut Managed, + config: &Config, + scoping: Scoping, + upload: &Addr, + referrer: &'static str, +) -> Option<()> where S: futures::Stream> + Send + 'static, E: Into> + 'static, @@ -597,7 +626,7 @@ where inner.set_attachment_length(byte_counter.get()); records.lenient(DataCategory::Attachment); // item was empty before }); - Some(item) + Some(()) } #[derive(Debug)] diff --git a/relay-server/src/endpoints/minidump.rs b/relay-server/src/endpoints/minidump.rs index 6259ce7361c..91df064822b 100644 --- a/relay-server/src/endpoints/minidump.rs +++ b/relay-server/src/endpoints/minidump.rs @@ -245,7 +245,8 @@ impl<'a> AttachmentStrategy for MinidumpAttachmentStrategy<'a> { upload_context.upload, "minidump", ) - .await) + .await + .ok()) } UploadDecision::Inline => read_inline(field, item).await, UploadDecision::Drop(limits) => { @@ -419,7 +420,7 @@ async fn raw_minidump_to_envelope( "minidump", ) .await - .ok_or(BadStoreRequest::ObjectstoreUploadFailed)?; + .map_err(|_| BadStoreRequest::ObjectstoreUploadFailed)?; } else { let minidump_data = request.extract().await?; item.try_modify(|inner, records| -> Result<(), BadStoreRequest> { diff --git a/relay-server/src/endpoints/playstation.rs b/relay-server/src/endpoints/playstation.rs index 5324bfbe444..41637bc0dfc 100644 --- a/relay-server/src/endpoints/playstation.rs +++ b/relay-server/src/endpoints/playstation.rs @@ -149,7 +149,8 @@ impl<'a> AttachmentStrategy for PlaystationAttachmentStrategy<'a> { upload_context.upload, "playstation", ) - .await) + .await + .ok()) } _ => match utils::read_bytes_into_item(field, item, config).await { // Don't bubble up errors caused by large attachments, skip over them and continue From b425577c95d1850df139e4ad0aa847a7900ca60c Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Mon, 11 May 2026 17:29:23 +0200 Subject: [PATCH 2/4] test --- tests/integration/test_minidump.py | 62 ++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/integration/test_minidump.py b/tests/integration/test_minidump.py index 1fbe24a4232..00952059c56 100644 --- a/tests/integration/test_minidump.py +++ b/tests/integration/test_minidump.py @@ -1,6 +1,7 @@ import os from unittest import mock +from flask import Response import msgpack import json @@ -984,6 +985,67 @@ def test_minidump_objectstore_uploads( assert minidump.payload.bytes == minidump_content +def test_minidump_objectstore_errors( + mini_sentry, + relay, +): + project_id = 42 + minidump_content = b"MDMP content" + log_content = b"Some log file content" + + project_config = mini_sentry.add_full_project_config(project_id) + project_config["config"].setdefault("features", []).append( + "projects:relay-minidump-attachment-uploads" + ) + mini_sentry.global_config["options"]["relay.endpoint-fetch-config.enabled"] = True + + @mini_sentry.app.route("/api//upload/", methods=["POST"]) + def create(**opts): + + return Response( + "Hell no", + status=400, + ) + + relay = relay( + mini_sentry, + options={ + "outcomes": { + "emit_outcomes": True, + "batch_size": 1, + "batch_interval": 1, + } + }, + ) + + relay.send_minidump( + project_id=project_id, + files=[ + (MINIDUMP_ATTACHMENT_NAME, "minidump.dmp", minidump_content), + ("logs", "log.txt", log_content), + ], + ) + + mini_sentry.captured_envelopes.get() + + assert mini_sentry.get_aggregated_outcomes() == [ + { + "category": 4, + "outcome": 3, + "project_id": 42, + "reason": "internal", + "quantity": 1, + }, + { + "category": 22, + "outcome": 3, + "project_id": 42, + "reason": "internal", + "quantity": 1, + }, + ] + + def test_size_limits_multipart_chunked(mini_sentry, relay): project_id = 42 From 50dd65d4f6c8a2a4f30f4c197fae04293f8c70a1 Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Mon, 11 May 2026 17:31:46 +0200 Subject: [PATCH 3/4] pretty --- tests/integration/test_minidump.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/test_minidump.py b/tests/integration/test_minidump.py index 00952059c56..07cdbb86e9e 100644 --- a/tests/integration/test_minidump.py +++ b/tests/integration/test_minidump.py @@ -1030,15 +1030,15 @@ def create(**opts): assert mini_sentry.get_aggregated_outcomes() == [ { - "category": 4, - "outcome": 3, + "category": DataCategory.ATTACHMENT, + "outcome": 3, # invalid "project_id": 42, "reason": "internal", "quantity": 1, }, { - "category": 22, - "outcome": 3, + "category": DataCategory.ATTACHMENT_ITEM, + "outcome": 3, # invalid "project_id": 42, "reason": "internal", "quantity": 1, From a3e05c79193ddda0e153b53798ae819b36023e85 Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Tue, 12 May 2026 09:05:56 +0200 Subject: [PATCH 4/4] implicit config --- tests/integration/test_minidump.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integration/test_minidump.py b/tests/integration/test_minidump.py index 07cdbb86e9e..aeb4cb9aa12 100644 --- a/tests/integration/test_minidump.py +++ b/tests/integration/test_minidump.py @@ -997,7 +997,6 @@ def test_minidump_objectstore_errors( project_config["config"].setdefault("features", []).append( "projects:relay-minidump-attachment-uploads" ) - mini_sentry.global_config["options"]["relay.endpoint-fetch-config.enabled"] = True @mini_sentry.app.route("/api//upload/", methods=["POST"]) def create(**opts):