根据你提供的
anemo::types::response::StatusCode 枚举定义,我发现它确实与 tonic::Code 没有直接一一对应的关系。我们需要根据语义进行合理映射。以下是修正后的转换实现:
优化后的状态码映射实现
rust
impl From<tonic::Code> for anemo::types::response::StatusCode {
fn from(code: tonic::Code) -> Self {
use anemo::types::response::StatusCode;
use tonic::Code;
match code {
Code::Ok => StatusCode::Success,
Code::Cancelled => StatusCode::RequestTimeout, // 客户端取消,映射为超时
Code::Unknown => StatusCode::Unknown,
Code::InvalidArgument => StatusCode::BadRequest,
Code::DeadlineExceeded => StatusCode::RequestTimeout,
Code::NotFound => StatusCode::NotFound,
Code::AlreadyExists => StatusCode::BadRequest, // 资源已存在,属于客户端错误
Code::PermissionDenied => StatusCode::BadRequest, // 权限问题通常是客户端问题
Code::ResourceExhausted => StatusCode::TooManyRequests,
Code::FailedPrecondition => StatusCode::BadRequest, // 前置条件失败
Code::Aborted => StatusCode::BadRequest, // 操作被中止
Code::OutOfRange => StatusCode::BadRequest, // 参数超出范围
Code::Unimplemented => StatusCode::VersionNotSupported, // 版本不支持或方法未实现
Code::Internal => StatusCode::InternalServerError,
Code::Unavailable => StatusCode::InternalServerError, // 服务不可用通常是内部问题
Code::DataLoss => StatusCode::InternalServerError,
Code::Unauthenticated => StatusCode::BadRequest, // 未认证属于客户端问题
}
}
}
// 优化后的处理函数
async fn handle_certificate_v2_impl_anemo(
&self,
request: anemo::Request<CertifiedTransaction>,
) -> Result<anemo::Response<HandleCertificateResponseV2>, anemo::rpc::Status> {
let response = self.handle_certificate_v2_impl(
tonic::Request::new(request.into_inner())
)
.await
.map(|(response, _weight)| response.into_inner())
.map_err(|tonic_status| {
// 转换状态码并保留原始错误消息
let status_code: anemo::types::response::StatusCode = tonic_status.code().into();
anemo::rpc::Status::new_with_message(status_code, tonic_status.message().to_string())
})?;
Ok(anemo::Response::new(response))
}
映射说明
- 客户端错误映射:InvalidArgument, AlreadyExists, PermissionDenied 等映射为 BadRequest (400)Unauthenticated 映射为 BadRequest (需要客户端提供认证)ResourceExhausted 映射为 TooManyRequests (429)
- 服务端错误映射:Internal, Unavailable, DataLoss 映射为 InternalServerError (500)Unimplemented 映射为 VersionNotSupported (505)
- 超时与取消:Cancelled, DeadlineExceeded 映射为 RequestTimeout (408)
这个映射方案基于 HTTP 状态码的语义,并根据 Tonic 和 Anemo 的错误类型进行了合理匹配。如果你的应用有特殊的错误处理需求,可以根据实际情况调整这个映射关系。