校验错误报告幂等事件集合

幂等命中时读取原归档并返回原事件 ID

相同 submissionId 重放事件集合不一致时返回 409
This commit is contained in:
2026-09-02 19:59:05 +08:00
parent ad775aaaee
commit 50d6245829
@@ -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::<Vec<_>>();
let existing_event_ids = existing_events
.iter()
.map(|event| event.event_id.clone())
.collect::<Vec<_>>();
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,
},
))