diff --git a/server-rs/crates/api-server/src/error_reports.rs b/server-rs/crates/api-server/src/error_reports.rs index 93dcf974c..7613dda39 100644 --- a/server-rs/crates/api-server/src/error_reports.rs +++ b/server-rs/crates/api-server/src/error_reports.rs @@ -192,21 +192,62 @@ pub async fn create_error_report( .with_message("报告元数据写入失败")); } }; - if record.batch_id != batch_id { + let accepted_event_ids = if record.batch_id != batch_id { + let existing_archive = oss + .get_object( + state.editor_oss_http_client(), + OssGetObjectRequest { + object_key: record.object_key.clone(), + max_bytes: MAX_BATCH_BYTES, + }, + ) + .await + .map_err(map_error_report_oss_error)?; + let (existing_events, _, _) = + parse_archive(&existing_archive).map_err(|e| internal(format!("报告归档损坏:{e}")))?; + let mut requested_event_ids = payload + .events + .iter() + .map(|event| event.event_id.clone()) + .collect::>(); + let existing_event_ids = existing_events + .iter() + .map(|event| event.event_id.clone()) + .collect::>(); + let mut existing_event_ids_sorted = existing_event_ids.clone(); + requested_event_ids.sort_unstable(); + existing_event_ids_sorted.sort_unstable(); + if requested_event_ids != existing_event_ids_sorted { + let _ = oss + .delete_object( + state.editor_oss_http_client(), + OssDeleteObjectRequest { object_key }, + ) + .await; + return Err(AppError::from_status(StatusCode::CONFLICT) + .with_message("相同 submissionId 的错误报告事件集合不一致")); + } let _ = oss .delete_object( state.editor_oss_http_client(), OssDeleteObjectRequest { object_key }, ) .await; - } + existing_event_ids + } else { + payload + .events + .into_iter() + .map(|event| event.event_id) + .collect() + }; Ok(json_success_body( Some(&ctx), CreateErrorReportBatchResponse { batch_id: record.batch_id, submission_id: record.submission_id, status: "ready".into(), - accepted_event_ids: payload.events.into_iter().map(|e| e.event_id).collect(), + accepted_event_ids, created_at: record.created_at, }, ))