rocketmq_error/unified/
network.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18//! Network-related errors for RocketMQ operations
19
20use thiserror::Error;
21
22/// Network operation errors
23#[derive(Debug, Error)]
24pub enum NetworkError {
25    /// Connection to remote address failed
26    #[error("Connection failed to {addr}: {reason}")]
27    ConnectionFailed { addr: String, reason: String },
28
29    /// Connection timeout
30    #[error("Connection timeout to {addr} after {timeout_ms}ms")]
31    ConnectionTimeout { addr: String, timeout_ms: u64 },
32
33    /// Connection was closed unexpectedly
34    #[error("Connection closed: {addr}")]
35    ConnectionClosed { addr: String },
36
37    /// Failed to send data
38    #[error("Send failed to {addr}: {reason}")]
39    SendFailed { addr: String, reason: String },
40
41    /// Failed to receive data
42    #[error("Receive failed from {addr}: {reason}")]
43    ReceiveFailed { addr: String, reason: String },
44
45    /// Invalid address format
46    #[error("Invalid address format: {addr}")]
47    InvalidAddress { addr: String },
48
49    /// DNS resolution failed
50    #[error("DNS resolution failed for {host}: {reason}")]
51    DnsResolutionFailed { host: String, reason: String },
52
53    /// Too many requests (backpressure)
54    #[error("Too many requests to {addr}, limit: {limit}")]
55    TooManyRequests { addr: String, limit: usize },
56
57    /// Request timeout
58    #[error("Request timeout to {addr} after {timeout_ms}ms")]
59    RequestTimeout { addr: String, timeout_ms: u64 },
60}
61
62impl NetworkError {
63    /// Create a connection failed error
64    #[inline]
65    pub fn connection_failed(addr: impl Into<String>, reason: impl Into<String>) -> Self {
66        Self::ConnectionFailed {
67            addr: addr.into(),
68            reason: reason.into(),
69        }
70    }
71
72    /// Create a connection timeout error
73    #[inline]
74    pub fn connection_timeout(addr: impl Into<String>, timeout_ms: u64) -> Self {
75        Self::ConnectionTimeout {
76            addr: addr.into(),
77            timeout_ms,
78        }
79    }
80
81    /// Create a send failed error
82    #[inline]
83    pub fn send_failed(addr: impl Into<String>, reason: impl Into<String>) -> Self {
84        Self::SendFailed {
85            addr: addr.into(),
86            reason: reason.into(),
87        }
88    }
89
90    /// Create a request timeout error
91    #[inline]
92    pub fn request_timeout(addr: impl Into<String>, timeout_ms: u64) -> Self {
93        Self::RequestTimeout {
94            addr: addr.into(),
95            timeout_ms,
96        }
97    }
98
99    /// Get the associated address if available
100    pub fn addr(&self) -> &str {
101        match self {
102            Self::ConnectionFailed { addr, .. }
103            | Self::ConnectionTimeout { addr, .. }
104            | Self::ConnectionClosed { addr }
105            | Self::SendFailed { addr, .. }
106            | Self::ReceiveFailed { addr, .. }
107            | Self::InvalidAddress { addr }
108            | Self::TooManyRequests { addr, .. }
109            | Self::RequestTimeout { addr, .. } => addr,
110            Self::DnsResolutionFailed { host, .. } => host,
111        }
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_network_error_creation() {
121        let err = NetworkError::connection_failed("127.0.0.1:9876", "timeout");
122        assert_eq!(err.addr(), "127.0.0.1:9876");
123        assert!(err.to_string().contains("Connection failed"));
124    }
125
126    #[test]
127    fn test_network_error_display() {
128        let err = NetworkError::ConnectionTimeout {
129            addr: "localhost:10911".to_string(),
130            timeout_ms: 3000,
131        };
132        assert_eq!(
133            err.to_string(),
134            "Connection timeout to localhost:10911 after 3000ms"
135        );
136    }
137}