Skip to main content

rocketmq_error/
recovery.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
15use std::fmt;
16
17/// Protocol-independent condition assigned by a canonical error descriptor.
18///
19/// A condition classifies the semantic outcome of a failure without adopting
20/// any boundary protocol's status-code vocabulary.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub enum CanonicalCondition {
23    /// The caller supplied an invalid argument.
24    InvalidArgument,
25    /// The requested resource does not exist.
26    NotFound,
27    /// The requested resource already exists.
28    AlreadyExists,
29    /// The caller has not been authenticated.
30    Unauthenticated,
31    /// The authenticated caller lacks permission.
32    PermissionDenied,
33    /// A required resource has been exhausted.
34    ResourceExhausted,
35    /// The system is not in a state that permits the operation.
36    FailedPrecondition,
37    /// The operation was aborted.
38    Aborted,
39    /// The service is unavailable.
40    Unavailable,
41    /// The operation exceeded its deadline.
42    DeadlineExceeded,
43    /// The system detected unrecoverable data loss.
44    DataLoss,
45    /// The operation was cancelled.
46    Cancelled,
47    /// The operation is not implemented.
48    Unimplemented,
49    /// An internal failure occurred.
50    Internal,
51}
52
53impl CanonicalCondition {
54    /// Returns the stable condition name used by catalog projections.
55    #[inline]
56    pub const fn as_str(self) -> &'static str {
57        match self {
58            Self::InvalidArgument => "invalid_argument",
59            Self::NotFound => "not_found",
60            Self::AlreadyExists => "already_exists",
61            Self::Unauthenticated => "unauthenticated",
62            Self::PermissionDenied => "permission_denied",
63            Self::ResourceExhausted => "resource_exhausted",
64            Self::FailedPrecondition => "failed_precondition",
65            Self::Aborted => "aborted",
66            Self::Unavailable => "unavailable",
67            Self::DeadlineExceeded => "deadline_exceeded",
68            Self::DataLoss => "data_loss",
69            Self::Cancelled => "cancelled",
70            Self::Unimplemented => "unimplemented",
71            Self::Internal => "internal",
72        }
73    }
74}
75
76impl fmt::Display for CanonicalCondition {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        f.write_str(self.as_str())
79    }
80}
81
82/// Catalog-owned recovery advice for a canonical error descriptor.
83///
84/// A recovery hint is not a retry decision and does not imply that an operation
85/// is retryable. Callers combine it with operation idempotency, stage, and
86/// remaining budget when deciding whether to retry.
87#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
88pub enum RecoveryHint {
89    /// Do not attempt recovery automatically.
90    Never,
91    /// Retry only after applying backoff.
92    Backoff,
93    /// Refresh route information before continuing.
94    RefreshRoute,
95    /// Refresh leader information before continuing.
96    RefreshLeader,
97    /// Select a different broker before continuing.
98    SwitchBroker,
99    /// Refresh credentials before continuing.
100    RefreshCredentials,
101    /// Require an operator to take corrective action.
102    OperatorAction,
103}
104
105impl RecoveryHint {
106    /// Returns the stable recovery-hint name used by catalog projections.
107    #[inline]
108    pub const fn as_str(self) -> &'static str {
109        match self {
110            Self::Never => "never",
111            Self::Backoff => "backoff",
112            Self::RefreshRoute => "refresh_route",
113            Self::RefreshLeader => "refresh_leader",
114            Self::SwitchBroker => "switch_broker",
115            Self::RefreshCredentials => "refresh_credentials",
116            Self::OperatorAction => "operator_action",
117        }
118    }
119}
120
121impl fmt::Display for RecoveryHint {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        f.write_str(self.as_str())
124    }
125}