use super::*;
use rocketmq_error::fields;
use rocketmq_error::Error;
use rocketmq_error::ErrorContext;
use rocketmq_transport::api::OutboundRequestContractReason;
use rocketmq_transport::api::OutboundRequestRejectionReason;
use rocketmq_transport::api::OutboundRequestStage;
use rocketmq_transport::api::TransportError;
pub(super) fn direct_invoke_result(
result: Result<OutboundRequestOutcome, TransportError>,
) -> ClientResult<RemotingCommand> {
match result {
Ok(OutboundRequestOutcome::Response(response)) => Ok(response),
Ok(OutboundRequestOutcome::Rejected(rejection)) => Err(match rejection.reason() {
OutboundRequestRejectionReason::DeadlineExpired => {
let mut context = ErrorContext::new().with_text(fields::OPERATION_DIAGNOSTIC, "client_invoke");
if let Some(timeout_millis) = rejection.timeout_millis() {
context = context.with_u64(fields::TIMEOUT_MS, timeout_millis);
}
ClientError::from_shared(Arc::new(
Error::new(&rocketmq_error::CORE_OPERATION_TIMED_OUT).with_context(context),
))
}
OutboundRequestRejectionReason::ClientStopping => {
ClientError::from_shared(Arc::new(Error::new(&rocketmq_error::CLIENT_LIFECYCLE_NOT_STARTED)))
}
OutboundRequestRejectionReason::QueueSaturated => ClientError::from_shared(Arc::new(Error::new(
&rocketmq_error::TRANSPORT_ADMISSION_QUEUE_SATURATED,
))),
OutboundRequestRejectionReason::Cancelled => {
direct_connection_error(request_stage_phase(rejection.stage()), rejection.remote_addr_present())
}
OutboundRequestRejectionReason::SessionClosed => {
direct_connection_error("closed", rejection.remote_addr_present())
}
OutboundRequestRejectionReason::EndpointUnavailable => {
direct_connection_error("connect", rejection.remote_addr_present())
}
}),
Ok(OutboundRequestOutcome::Contract(contract)) => Err(match contract.reason() {
OutboundRequestContractReason::NameServerEndpointMissing => {
direct_connection_error("connect", contract.remote_addr_present())
}
}),
Err(error) => Err(ClientError::from_shared(error.into_shared_error())),
}
}
fn direct_connection_error(phase: &'static str, remote_addr_present: bool) -> ClientError {
let mut context = ErrorContext::new().with_text(fields::PHASE, phase);
if remote_addr_present {
context = context.with_secret_presence(fields::REMOTE_ADDR_PRESENT);
}
ClientError::from_shared(Arc::new(
Error::new(&rocketmq_error::TRANSPORT_CONNECTION_FAILED).with_context(context),
))
}
const fn request_stage_phase(stage: OutboundRequestStage) -> &'static str {
match stage {
OutboundRequestStage::BeforeWrite => "before_write",
OutboundRequestStage::Writing => "writing",
OutboundRequestStage::AwaitingResponse => "awaiting_response",
OutboundRequestStage::ResponseReceived => "response_received",
}
}