Skip to main content

rocketmq_error/unified/
rpc.rs

1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! RPC client errors with full context preservation
16
17use thiserror::Error;
18
19/// RPC client specific errors with full context preservation
20#[derive(Error, Debug)]
21pub enum RpcClientError {
22    /// Broker address not found in client metadata
23    #[error("Broker '{broker_name}' address not found in client metadata")]
24    BrokerNotFound { broker_name: String },
25
26    /// RPC request failed
27    #[error("RPC request failed: addr={addr}, request_code={request_code}, timeout={timeout_ms}ms")]
28    RequestFailed {
29        addr: String,
30        request_code: i32,
31        timeout_ms: u64,
32        #[source]
33        source: Box<dyn std::error::Error + Send + Sync>,
34    },
35
36    /// Unexpected response code received
37    #[error("Unexpected response code: {code} ({code_name})")]
38    UnexpectedResponseCode { code: i32, code_name: String },
39
40    /// Request code not supported by the handler
41    #[error("Request code not supported: {code}")]
42    UnsupportedRequestCode { code: i32 },
43
44    /// RPC error from remote server
45    #[error("RPC error from remote: code={0}, message={1}")]
46    RemoteError(i32, String),
47}
48
49impl RpcClientError {
50    /// Helper to construct a `BrokerNotFound` error.
51    pub fn broker_not_found(broker_name: impl Into<String>) -> Self {
52        RpcClientError::BrokerNotFound {
53            broker_name: broker_name.into(),
54        }
55    }
56    /// Helper to construct a `RequestFailed` error.
57    pub fn request_failed<E>(addr: impl Into<String>, request_code: i32, timeout_ms: u64, source: E) -> Self
58    where
59        E: std::error::Error + Send + Sync + 'static,
60    {
61        RpcClientError::RequestFailed {
62            addr: addr.into(),
63            request_code,
64            timeout_ms,
65            source: Box::new(source),
66        }
67    }
68    /// Helper to construct an `UnexpectedResponseCode` error.
69    pub fn unexpected_response_code(code: i32, code_name: impl Into<String>) -> Self {
70        RpcClientError::UnexpectedResponseCode {
71            code,
72            code_name: code_name.into(),
73        }
74    }
75    /// Helper to construct an `UnsupportedRequestCode` error.
76    pub fn unsupported_request_code(code: i32) -> Self {
77        RpcClientError::UnsupportedRequestCode { code }
78    }
79    /// Helper to construct a `RemoteError`.
80    pub fn remote_error(code: i32, message: impl Into<String>) -> Self {
81        RpcClientError::RemoteError(code, message.into())
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88    use std::io;
89
90    #[test]
91    fn test_rpc_client_error() {
92        let err = RpcClientError::broker_not_found("broker-a");
93        assert_eq!(
94            err.to_string(),
95            "Broker 'broker-a' address not found in client metadata"
96        );
97
98        let source = io::Error::other("network error");
99        let err = RpcClientError::request_failed("127.0.0.1:10911", 10, 3000, source);
100        assert_eq!(
101            err.to_string(),
102            "RPC request failed: addr=127.0.0.1:10911, request_code=10, timeout=3000ms"
103        );
104
105        let err = RpcClientError::unexpected_response_code(1, "SYSTEM_ERROR");
106        assert_eq!(err.to_string(), "Unexpected response code: 1 (SYSTEM_ERROR)");
107
108        let err = RpcClientError::unsupported_request_code(100);
109        assert_eq!(err.to_string(), "Request code not supported: 100");
110
111        let err = RpcClientError::remote_error(2, "topic not exist");
112        assert_eq!(
113            err.to_string(),
114            "RPC error from remote: code=2, message=topic not exist"
115        );
116    }
117}