Skip to main content

common_meta/error/retry_hint/
etcd.rs

1// Copyright 2023 Greptime Team
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
15use common_error::ext::{RetryHint, retry_hint_from_io_error};
16
17/// Converts an etcd client error into a conservative retry hint.
18pub fn retry_hint_from_etcd_error(error: &etcd_client::Error) -> RetryHint {
19    match error {
20        etcd_client::Error::IoError(error) => retry_hint_from_io_error(error),
21        etcd_client::Error::TransportError(_)
22        | etcd_client::Error::EndpointError(_)
23        | etcd_client::Error::WatchError(_)
24        | etcd_client::Error::LeaseKeepAliveError(_)
25        | etcd_client::Error::ElectError(_) => RetryHint::Retryable,
26        etcd_client::Error::GRpcStatus(status) => retry_hint_from_etcd_grpc_code(status.code()),
27        etcd_client::Error::InvalidArgs(_)
28        | etcd_client::Error::InvalidUri(_)
29        | etcd_client::Error::Utf8Error(_)
30        | etcd_client::Error::InvalidHeaderValue(_)
31        | etcd_client::Error::EndpointsNotManaged => RetryHint::NonRetryable,
32    }
33}
34
35/// Converts a tonic status code from an external backend into a retry hint.
36fn retry_hint_from_etcd_grpc_code(code: tonic::Code) -> RetryHint {
37    match code {
38        tonic::Code::Unavailable | tonic::Code::DeadlineExceeded | tonic::Code::Aborted => {
39            RetryHint::Retryable
40        }
41        _ => RetryHint::NonRetryable,
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use common_error::ext::RetryHint;
48
49    use super::*;
50
51    #[test]
52    fn test_etcd_grpc_status_retry_hint() {
53        assert_eq!(
54            retry_hint_from_etcd_grpc_code(tonic::Code::Unavailable),
55            RetryHint::Retryable
56        );
57        assert_eq!(
58            retry_hint_from_etcd_grpc_code(tonic::Code::DeadlineExceeded),
59            RetryHint::Retryable
60        );
61        assert_eq!(
62            retry_hint_from_etcd_grpc_code(tonic::Code::Aborted),
63            RetryHint::Retryable
64        );
65        assert_eq!(
66            retry_hint_from_etcd_grpc_code(tonic::Code::ResourceExhausted),
67            RetryHint::NonRetryable
68        );
69        assert_eq!(
70            retry_hint_from_etcd_grpc_code(tonic::Code::InvalidArgument),
71            RetryHint::NonRetryable
72        );
73    }
74}