1use std::any::Any;
16use std::io::Error as IoError;
17use std::sync::Arc;
18
19use common_error::ext::{BoxedError, ErrorExt};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use snafu::{Location, Snafu};
23
24use crate::inverted_index::search::predicate::Predicate;
25
26#[derive(Snafu)]
27#[snafu(visibility(pub))]
28#[stack_trace_debug]
29pub enum Error {
30 #[snafu(display("Failed to read"))]
31 Read {
32 #[snafu(source)]
33 error: IoError,
34 #[snafu(implicit)]
35 location: Location,
36 },
37
38 #[snafu(display("Failed to write"))]
39 Write {
40 #[snafu(source)]
41 error: IoError,
42 #[snafu(implicit)]
43 location: Location,
44 },
45
46 #[snafu(display("Failed to flush"))]
47 Flush {
48 #[snafu(source)]
49 error: IoError,
50 #[snafu(implicit)]
51 location: Location,
52 },
53
54 #[snafu(display("Failed to close"))]
55 Close {
56 #[snafu(source)]
57 error: IoError,
58 #[snafu(implicit)]
59 location: Location,
60 },
61
62 #[snafu(display(
63 "Unexpected inverted index blob size, min: {min_blob_size}, actual: {actual_blob_size}"
64 ))]
65 UnexpectedBlobSize {
66 min_blob_size: u64,
67 actual_blob_size: u64,
68 #[snafu(implicit)]
69 location: Location,
70 },
71
72 #[snafu(display("Blob size too small"))]
73 BlobSizeTooSmall {
74 #[snafu(implicit)]
75 location: Location,
76 },
77
78 #[snafu(display("Invalid footer payload size"))]
79 InvalidFooterPayloadSize {
80 #[snafu(implicit)]
81 location: Location,
82 },
83
84 #[snafu(display(
85 "Unexpected inverted index footer payload size, max: {max_payload_size}, actual: {actual_payload_size}"
86 ))]
87 UnexpectedFooterPayloadSize {
88 max_payload_size: u64,
89 actual_payload_size: u64,
90 #[snafu(implicit)]
91 location: Location,
92 },
93
94 #[snafu(display(
95 "Unexpected inverted index offset size, offset: {offset}, size: {size}, blob_size: {blob_size}, payload_size: {payload_size}"
96 ))]
97 UnexpectedOffsetSize {
98 offset: u64,
99 size: u64,
100 blob_size: u64,
101 payload_size: u64,
102 },
103
104 #[snafu(display("Unexpected zero segment row count"))]
105 UnexpectedZeroSegmentRowCount {
106 #[snafu(implicit)]
107 location: Location,
108 },
109
110 #[snafu(display("Failed to decode fst"))]
111 DecodeFst {
112 #[snafu(source)]
113 error: fst::Error,
114 #[snafu(implicit)]
115 location: Location,
116 },
117
118 #[snafu(display("Failed to decode bitmap"))]
119 DecodeBitmap {
120 #[snafu(source)]
121 error: IoError,
122 #[snafu(implicit)]
123 location: Location,
124 },
125
126 #[snafu(display("Failed to decode protobuf"))]
127 DecodeProto {
128 #[snafu(source)]
129 error: prost::DecodeError,
130 #[snafu(implicit)]
131 location: Location,
132 },
133
134 #[snafu(display("Failed to parse regex pattern: {pattern}"))]
135 ParseRegex {
136 #[snafu(source)]
137 error: regex::Error,
138 pattern: String,
139 #[snafu(implicit)]
140 location: Location,
141 },
142
143 #[snafu(display("Failed to parse regex DFA"))]
144 ParseDFA {
145 #[snafu(source)]
146 error: Box<regex_automata::dfa::dense::BuildError>,
147 #[snafu(implicit)]
148 location: Location,
149 },
150
151 #[snafu(display("Unexpected empty predicates to construct fst applier"))]
152 EmptyPredicates {
153 #[snafu(implicit)]
154 location: Location,
155 },
156
157 #[snafu(display("Failed to construct intersection fst applier with InList predicate"))]
158 IntersectionApplierWithInList {
159 #[snafu(implicit)]
160 location: Location,
161 },
162
163 #[snafu(display("Failed to construct keys fst applier without InList predicate"))]
164 KeysApplierWithoutInList {
165 #[snafu(implicit)]
166 location: Location,
167 },
168
169 #[snafu(display(
170 "Failed to construct keys fst applier with unexpected predicates: {predicates:?}"
171 ))]
172 KeysApplierUnexpectedPredicates {
173 #[snafu(implicit)]
174 location: Location,
175 predicates: Vec<Predicate>,
176 },
177
178 #[snafu(display("index not found, name: {name}"))]
179 IndexNotFound {
180 name: String,
181 #[snafu(implicit)]
182 location: Location,
183 },
184
185 #[snafu(display("Failed to insert value to FST"))]
186 FstInsert {
187 #[snafu(source)]
188 error: fst::Error,
189 #[snafu(implicit)]
190 location: Location,
191 },
192
193 #[snafu(display("Failed to compile FST"))]
194 FstCompile {
195 #[snafu(source)]
196 error: fst::Error,
197 #[snafu(implicit)]
198 location: Location,
199 },
200
201 #[snafu(display("Failed to perform IO operation"))]
202 CommonIo {
203 #[snafu(source)]
204 error: IoError,
205 #[snafu(implicit)]
206 location: Location,
207 },
208
209 #[snafu(display("Unknown intermediate codec magic: {magic:?}"))]
210 UnknownIntermediateCodecMagic {
211 magic: [u8; 4],
212 #[snafu(implicit)]
213 location: Location,
214 },
215
216 #[snafu(display(
217 "Inconsistent row count, index_name: {index_name}, total_row_count: {total_row_count}, expected: {expected_row_count}"
218 ))]
219 InconsistentRowCount {
220 index_name: String,
221 total_row_count: usize,
222 expected_row_count: usize,
223 },
224
225 #[snafu(display("Shared index metadata read failed"))]
226 SharedRead {
227 source: Arc<Error>,
228 #[snafu(implicit)]
229 location: Location,
230 },
231
232 #[snafu(display("External error"))]
233 External {
234 source: BoxedError,
235 #[snafu(implicit)]
236 location: Location,
237 },
238
239 #[snafu(display("Intermediate error"))]
240 Intermediate {
241 source: crate::error::Error,
242 #[snafu(implicit)]
243 location: Location,
244 },
245}
246
247impl ErrorExt for Error {
248 fn status_code(&self) -> StatusCode {
249 use Error::*;
250 match self {
251 Read { .. }
252 | Write { .. }
253 | Flush { .. }
254 | Close { .. }
255 | UnexpectedFooterPayloadSize { .. }
256 | UnexpectedZeroSegmentRowCount { .. }
257 | UnexpectedOffsetSize { .. }
258 | UnexpectedBlobSize { .. }
259 | DecodeProto { .. }
260 | DecodeFst { .. }
261 | KeysApplierUnexpectedPredicates { .. }
262 | CommonIo { .. }
263 | UnknownIntermediateCodecMagic { .. }
264 | FstCompile { .. }
265 | DecodeBitmap { .. }
266 | InvalidFooterPayloadSize { .. }
267 | BlobSizeTooSmall { .. } => StatusCode::Unexpected,
268
269 ParseRegex { .. }
270 | ParseDFA { .. }
271 | KeysApplierWithoutInList { .. }
272 | IntersectionApplierWithInList { .. }
273 | EmptyPredicates { .. }
274 | FstInsert { .. }
275 | InconsistentRowCount { .. }
276 | IndexNotFound { .. } => StatusCode::InvalidArguments,
277
278 Intermediate { source, .. } => source.status_code(),
279 External { source, .. } => source.status_code(),
280 SharedRead { source, .. } => source.status_code(),
281 }
282 }
283
284 fn as_any(&self) -> &dyn Any {
285 self
286 }
287}
288
289pub type Result<T> = std::result::Result<T, Error>;
290
291#[cfg(test)]
292mod tests {
293 use snafu::IntoError;
294
295 use super::*;
296
297 #[test]
298 fn shared_metadata_error_preserves_status() {
299 let source = CommonIoSnafu.into_error(std::io::Error::other("read failed"));
300 let status = source.status_code();
301 let retry = source.retry_hint();
302 let error = SharedReadSnafu.into_error(Arc::new(source));
303 assert_eq!(error.status_code(), status);
304 assert_eq!(error.retry_hint(), retry);
305 }
306}