1use std::any::Any;
16use std::sync::Arc;
17
18use common_error::ext::{BoxedError, ErrorExt, RetryHint};
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use datatypes::prelude::ConcreteDataType;
22use snafu::{Location, Snafu};
23use store_api::region_request::RegionRequest;
24use store_api::storage::{FileId, RegionId};
25
26#[derive(Snafu)]
27#[snafu(visibility(pub))]
28#[stack_trace_debug]
29pub enum Error {
30 #[snafu(display("Failed to create mito region, region type: {}", region_type))]
31 CreateMitoRegion {
32 region_type: String,
33 source: BoxedError,
34 #[snafu(implicit)]
35 location: Location,
36 },
37
38 #[snafu(display("Failed to open mito region, region type: {}", region_type))]
39 OpenMitoRegion {
40 region_type: String,
41 source: BoxedError,
42 #[snafu(implicit)]
43 location: Location,
44 },
45
46 #[snafu(display("Failed to clean up mito region, region type: {}", region_type))]
47 CleanUpMitoRegion {
48 region_type: String,
49 source: BoxedError,
50 #[snafu(implicit)]
51 location: Location,
52 },
53
54 #[snafu(display("Failed to batch open mito region"))]
55 BatchOpenMitoRegion {
56 source: BoxedError,
57 #[snafu(implicit)]
58 location: Location,
59 },
60
61 #[snafu(display("Failed to batch catchup mito region"))]
62 BatchCatchupMitoRegion {
63 source: BoxedError,
64 #[snafu(implicit)]
65 location: Location,
66 },
67
68 #[snafu(display("No open region result for region {}", region_id))]
69 NoOpenRegionResult {
70 region_id: RegionId,
71 #[snafu(implicit)]
72 location: Location,
73 },
74
75 #[snafu(display("Failed to close mito region, region id: {}", region_id))]
76 CloseMitoRegion {
77 region_id: RegionId,
78 source: BoxedError,
79 #[snafu(implicit)]
80 location: Location,
81 },
82
83 #[snafu(display("Failed to deserialize column metadata from {}", raw))]
84 DeserializeColumnMetadata {
85 raw: String,
86 #[snafu(source)]
87 error: serde_json::Error,
88 #[snafu(implicit)]
89 location: Location,
90 },
91
92 #[snafu(display("Failed to serialize column metadata"))]
93 SerializeColumnMetadata {
94 #[snafu(source)]
95 error: serde_json::Error,
96 #[snafu(implicit)]
97 location: Location,
98 },
99
100 #[snafu(display("Failed to serialize region manifest info"))]
101 SerializeRegionManifestInfo {
102 #[snafu(source)]
103 error: serde_json::Error,
104 #[snafu(implicit)]
105 location: Location,
106 },
107
108 #[snafu(display("Failed to decode base64 column value"))]
109 DecodeColumnValue {
110 #[snafu(source)]
111 error: base64::DecodeError,
112 #[snafu(implicit)]
113 location: Location,
114 },
115
116 #[snafu(display("Failed to parse region id from {}", raw))]
117 ParseRegionId {
118 raw: String,
119 #[snafu(source)]
120 error: <u64 as std::str::FromStr>::Err,
121 #[snafu(implicit)]
122 location: Location,
123 },
124
125 #[snafu(display("Failed to parse region options: {}", reason))]
126 ParseRegionOptions {
127 reason: String,
128 #[snafu(implicit)]
129 location: Location,
130 },
131
132 #[snafu(display("Mito read operation fails"))]
133 MitoReadOperation {
134 source: BoxedError,
135 #[snafu(implicit)]
136 location: Location,
137 },
138
139 #[snafu(display(
140 "Mito copy region from operation fails, source region id: {}, target region id: {}",
141 source_region_id,
142 target_region_id
143 ))]
144 MitoCopyRegionFromOperation {
145 source: BoxedError,
146 #[snafu(implicit)]
147 location: Location,
148 source_region_id: RegionId,
149 target_region_id: RegionId,
150 },
151
152 #[snafu(display("Mito edit region operation fails, region id: {}", region_id))]
153 MitoEditRegion {
154 region_id: RegionId,
155 source: BoxedError,
156 #[snafu(implicit)]
157 location: Location,
158 },
159
160 #[snafu(display("Failed to encode primary key"))]
161 EncodePrimaryKey {
162 source: mito_codec::error::Error,
163 #[snafu(implicit)]
164 location: Location,
165 },
166
167 #[snafu(display("Mito write operation fails"))]
168 MitoWriteOperation {
169 source: BoxedError,
170 #[snafu(implicit)]
171 location: Location,
172 },
173
174 #[snafu(display("Mito flush operation fails"))]
175 MitoFlushOperation {
176 source: BoxedError,
177 #[snafu(implicit)]
178 location: Location,
179 },
180
181 #[snafu(display("Mito truncate operation fails"))]
182 MitoTruncateOperation {
183 source: BoxedError,
184 #[snafu(implicit)]
185 location: Location,
186 },
187
188 #[snafu(display("Mito sync operation fails"))]
189 MitoSyncOperation {
190 source: BoxedError,
191 #[snafu(implicit)]
192 location: Location,
193 },
194
195 #[snafu(display("Mito enter staging operation fails"))]
196 MitoEnterStagingOperation {
197 source: BoxedError,
198 #[snafu(implicit)]
199 location: Location,
200 },
201
202 #[snafu(display("Failed to collect record batch stream"))]
203 CollectRecordBatchStream {
204 source: common_recordbatch::error::Error,
205 #[snafu(implicit)]
206 location: Location,
207 },
208
209 #[snafu(display("Internal column {} is reserved", column))]
210 InternalColumnOccupied {
211 column: String,
212 #[snafu(implicit)]
213 location: Location,
214 },
215
216 #[snafu(display("Required table option is missing"))]
217 MissingRegionOption {
218 #[snafu(implicit)]
219 location: Location,
220 },
221
222 #[snafu(display("Region options are conflicted"))]
223 ConflictRegionOption {
224 #[snafu(implicit)]
225 location: Location,
226 },
227
228 #[snafu(display("Physical region {} not found", region_id))]
229 PhysicalRegionNotFound {
230 region_id: RegionId,
231 #[snafu(implicit)]
232 location: Location,
233 },
234
235 #[snafu(display("Logical region {} not found", region_id))]
236 LogicalRegionNotFound {
237 region_id: RegionId,
238 #[snafu(implicit)]
239 location: Location,
240 },
241
242 #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
243 ColumnTypeMismatch {
244 expect: ConcreteDataType,
245 actual: ConcreteDataType,
246 #[snafu(implicit)]
247 location: Location,
248 },
249
250 #[snafu(display("Column {} not found in logical region {}", name, region_id))]
251 ColumnNotFound {
252 name: String,
253 region_id: RegionId,
254 #[snafu(implicit)]
255 location: Location,
256 },
257
258 #[snafu(display("Table id count mismatch. Expect {}, got {}", expected, actual))]
259 TableIdCountMismatch {
260 expected: usize,
261 actual: usize,
262 #[snafu(implicit)]
263 location: Location,
264 },
265
266 #[snafu(display("Alter request to physical region is forbidden"))]
267 ForbiddenPhysicalAlter {
268 #[snafu(implicit)]
269 location: Location,
270 },
271
272 #[snafu(display("Write request to physical region is forbidden"))]
273 ForbiddenPhysicalWrite {
274 #[snafu(implicit)]
275 location: Location,
276 },
277
278 #[snafu(display("Invalid region metadata"))]
279 InvalidMetadata {
280 source: store_api::metadata::MetadataError,
281 #[snafu(implicit)]
282 location: Location,
283 },
284
285 #[snafu(display("Invalid request for region {}, reason: {}", region_id, reason))]
286 InvalidRequest {
287 reason: String,
288 region_id: RegionId,
289 #[snafu(implicit)]
290 location: Location,
291 },
292
293 #[snafu(display(
294 "Physical region {} is busy, there are still some logical regions using it",
295 region_id
296 ))]
297 PhysicalRegionBusy {
298 region_id: RegionId,
299 #[snafu(implicit)]
300 location: Location,
301 },
302
303 #[snafu(display("Unsupported region request: {}", request))]
304 UnsupportedRegionRequest {
305 request: Box<RegionRequest>,
306 #[snafu(implicit)]
307 location: Location,
308 },
309
310 #[snafu(display("Unsupported remap manifests request for region {}", region_id))]
311 UnsupportedRemapManifestsRequest {
312 region_id: RegionId,
313 #[snafu(implicit)]
314 location: Location,
315 },
316
317 #[snafu(display("Unsupported sync region from request for region {}", region_id))]
318 UnsupportedSyncRegionFromRequest {
319 region_id: RegionId,
320 #[snafu(implicit)]
321 location: Location,
322 },
323
324 #[snafu(display("Missing file metas in region {}, file ids: {:?}", region_id, file_ids))]
325 MissingFiles {
326 region_id: RegionId,
327 #[snafu(implicit)]
328 location: Location,
329 file_ids: Vec<FileId>,
330 },
331
332 #[snafu(display("Unsupported alter kind: {}", kind))]
333 UnsupportedAlterKind {
334 kind: String,
335 #[snafu(implicit)]
336 location: Location,
337 },
338
339 #[snafu(display("Multiple field column found: {} and {}", previous, current))]
340 MultipleFieldColumn {
341 previous: String,
342 current: String,
343 #[snafu(implicit)]
344 location: Location,
345 },
346
347 #[snafu(display("Adding field column {} to physical table", name))]
348 AddingFieldColumn {
349 name: String,
350 #[snafu(implicit)]
351 location: Location,
352 },
353
354 #[snafu(display("No field column found"))]
355 NoFieldColumn {
356 #[snafu(implicit)]
357 location: Location,
358 },
359
360 #[snafu(display("Failed to set SKIPPING index option"))]
361 SetSkippingIndexOption {
362 source: datatypes::error::Error,
363 #[snafu(implicit)]
364 location: Location,
365 },
366
367 #[snafu(display(
368 "Failed to create default value for column {} of region {}",
369 column,
370 region_id
371 ))]
372 CreateDefault {
373 region_id: RegionId,
374 column: String,
375 source: datatypes::error::Error,
376 #[snafu(implicit)]
377 location: Location,
378 },
379
380 #[snafu(display("Unexpected request: {}", reason))]
381 UnexpectedRequest {
382 reason: String,
383 #[snafu(implicit)]
384 location: Location,
385 },
386
387 #[snafu(display("Expected metric manifest info, region: {}", region_id))]
388 MetricManifestInfo {
389 region_id: RegionId,
390 #[snafu(implicit)]
391 location: Location,
392 },
393
394 #[snafu(display("Failed to start repeated task: {}", name))]
395 StartRepeatedTask {
396 name: String,
397 source: common_runtime::error::Error,
398 #[snafu(implicit)]
399 location: Location,
400 },
401
402 #[snafu(display("Get value from cache"))]
403 CacheGet {
404 source: Arc<Error>,
405 #[snafu(implicit)]
406 location: Location,
407 },
408}
409
410pub type Result<T, E = Error> = std::result::Result<T, E>;
411
412impl ErrorExt for Error {
413 fn status_code(&self) -> StatusCode {
414 use Error::*;
415
416 match self {
417 InternalColumnOccupied { .. }
418 | MissingRegionOption { .. }
419 | ConflictRegionOption { .. }
420 | ColumnTypeMismatch { .. }
421 | TableIdCountMismatch { .. }
422 | PhysicalRegionBusy { .. }
423 | MultipleFieldColumn { .. }
424 | NoFieldColumn { .. }
425 | AddingFieldColumn { .. }
426 | ParseRegionOptions { .. }
427 | UnexpectedRequest { .. }
428 | UnsupportedAlterKind { .. }
429 | UnsupportedRemapManifestsRequest { .. }
430 | UnsupportedSyncRegionFromRequest { .. }
431 | InvalidRequest { .. }
432 | CreateDefault { .. } => StatusCode::InvalidArguments,
433
434 ForbiddenPhysicalAlter { .. }
435 | ForbiddenPhysicalWrite { .. }
436 | UnsupportedRegionRequest { .. }
437 | MissingFiles { .. } => StatusCode::Unsupported,
438
439 DeserializeColumnMetadata { .. }
440 | SerializeColumnMetadata { .. }
441 | DecodeColumnValue { .. }
442 | ParseRegionId { .. }
443 | InvalidMetadata { .. }
444 | SetSkippingIndexOption { .. }
445 | SerializeRegionManifestInfo { .. }
446 | NoOpenRegionResult { .. } => StatusCode::Unexpected,
447
448 PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
449 StatusCode::RegionNotFound
450 }
451
452 ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
453
454 CreateMitoRegion { source, .. }
455 | OpenMitoRegion { source, .. }
456 | CleanUpMitoRegion { source, .. }
457 | CloseMitoRegion { source, .. }
458 | MitoReadOperation { source, .. }
459 | MitoWriteOperation { source, .. }
460 | MitoFlushOperation { source, .. }
461 | MitoTruncateOperation { source, .. }
462 | MitoSyncOperation { source, .. }
463 | MitoEnterStagingOperation { source, .. }
464 | BatchOpenMitoRegion { source, .. }
465 | BatchCatchupMitoRegion { source, .. }
466 | MitoCopyRegionFromOperation { source, .. }
467 | MitoEditRegion { source, .. } => source.status_code(),
468
469 EncodePrimaryKey { source, .. } => source.status_code(),
470
471 CollectRecordBatchStream { source, .. } => source.status_code(),
472
473 StartRepeatedTask { source, .. } => source.status_code(),
474
475 MetricManifestInfo { .. } => StatusCode::Internal,
476
477 CacheGet { source, .. } => source.status_code(),
478 }
479 }
480
481 fn as_any(&self) -> &dyn Any {
482 self
483 }
484
485 fn retry_hint(&self) -> RetryHint {
486 use Error::*;
487
488 match self {
489 CreateMitoRegion { source, .. }
490 | OpenMitoRegion { source, .. }
491 | CleanUpMitoRegion { source, .. }
492 | BatchOpenMitoRegion { source, .. }
493 | BatchCatchupMitoRegion { source, .. }
494 | CloseMitoRegion { source, .. }
495 | MitoReadOperation { source, .. }
496 | MitoWriteOperation { source, .. }
497 | MitoFlushOperation { source, .. }
498 | MitoTruncateOperation { source, .. }
499 | MitoSyncOperation { source, .. }
500 | MitoEnterStagingOperation { source, .. }
501 | MitoCopyRegionFromOperation { source, .. }
502 | MitoEditRegion { source, .. } => source.retry_hint(),
503
504 EncodePrimaryKey { source, .. } => source.retry_hint(),
505 CollectRecordBatchStream { source, .. } => source.retry_hint(),
506 StartRepeatedTask { source, .. } => source.retry_hint(),
507 CacheGet { source, .. } => source.retry_hint(),
508
509 _ => RetryHint::NonRetryable,
510 }
511 }
512}