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}