Skip to main content

metric_engine/
error.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 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 sync operation fails"))]
182    MitoSyncOperation {
183        source: BoxedError,
184        #[snafu(implicit)]
185        location: Location,
186    },
187
188    #[snafu(display("Mito enter staging operation fails"))]
189    MitoEnterStagingOperation {
190        source: BoxedError,
191        #[snafu(implicit)]
192        location: Location,
193    },
194
195    #[snafu(display("Failed to collect record batch stream"))]
196    CollectRecordBatchStream {
197        source: common_recordbatch::error::Error,
198        #[snafu(implicit)]
199        location: Location,
200    },
201
202    #[snafu(display("Internal column {} is reserved", column))]
203    InternalColumnOccupied {
204        column: String,
205        #[snafu(implicit)]
206        location: Location,
207    },
208
209    #[snafu(display("Required table option is missing"))]
210    MissingRegionOption {
211        #[snafu(implicit)]
212        location: Location,
213    },
214
215    #[snafu(display("Region options are conflicted"))]
216    ConflictRegionOption {
217        #[snafu(implicit)]
218        location: Location,
219    },
220
221    #[snafu(display("Physical region {} not found", region_id))]
222    PhysicalRegionNotFound {
223        region_id: RegionId,
224        #[snafu(implicit)]
225        location: Location,
226    },
227
228    #[snafu(display("Logical region {} not found", region_id))]
229    LogicalRegionNotFound {
230        region_id: RegionId,
231        #[snafu(implicit)]
232        location: Location,
233    },
234
235    #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
236    ColumnTypeMismatch {
237        expect: ConcreteDataType,
238        actual: ConcreteDataType,
239        #[snafu(implicit)]
240        location: Location,
241    },
242
243    #[snafu(display("Column {} not found in logical region {}", name, region_id))]
244    ColumnNotFound {
245        name: String,
246        region_id: RegionId,
247        #[snafu(implicit)]
248        location: Location,
249    },
250
251    #[snafu(display("Table id count mismatch. Expect {}, got {}", expected, actual))]
252    TableIdCountMismatch {
253        expected: usize,
254        actual: usize,
255        #[snafu(implicit)]
256        location: Location,
257    },
258
259    #[snafu(display("Alter request to physical region is forbidden"))]
260    ForbiddenPhysicalAlter {
261        #[snafu(implicit)]
262        location: Location,
263    },
264
265    #[snafu(display("Write request to physical region is forbidden"))]
266    ForbiddenPhysicalWrite {
267        #[snafu(implicit)]
268        location: Location,
269    },
270
271    #[snafu(display("Invalid region metadata"))]
272    InvalidMetadata {
273        source: store_api::metadata::MetadataError,
274        #[snafu(implicit)]
275        location: Location,
276    },
277
278    #[snafu(display("Invalid request for region {}, reason: {}", region_id, reason))]
279    InvalidRequest {
280        reason: String,
281        region_id: RegionId,
282        #[snafu(implicit)]
283        location: Location,
284    },
285
286    #[snafu(display(
287        "Physical region {} is busy, there are still some logical regions using it",
288        region_id
289    ))]
290    PhysicalRegionBusy {
291        region_id: RegionId,
292        #[snafu(implicit)]
293        location: Location,
294    },
295
296    #[snafu(display("Unsupported region request: {}", request))]
297    UnsupportedRegionRequest {
298        request: Box<RegionRequest>,
299        #[snafu(implicit)]
300        location: Location,
301    },
302
303    #[snafu(display("Unsupported remap manifests request for region {}", region_id))]
304    UnsupportedRemapManifestsRequest {
305        region_id: RegionId,
306        #[snafu(implicit)]
307        location: Location,
308    },
309
310    #[snafu(display("Unsupported sync region from request for region {}", region_id))]
311    UnsupportedSyncRegionFromRequest {
312        region_id: RegionId,
313        #[snafu(implicit)]
314        location: Location,
315    },
316
317    #[snafu(display("Missing file metas in region {}, file ids: {:?}", region_id, file_ids))]
318    MissingFiles {
319        region_id: RegionId,
320        #[snafu(implicit)]
321        location: Location,
322        file_ids: Vec<FileId>,
323    },
324
325    #[snafu(display("Unsupported alter kind: {}", kind))]
326    UnsupportedAlterKind {
327        kind: String,
328        #[snafu(implicit)]
329        location: Location,
330    },
331
332    #[snafu(display("Multiple field column found: {} and {}", previous, current))]
333    MultipleFieldColumn {
334        previous: String,
335        current: String,
336        #[snafu(implicit)]
337        location: Location,
338    },
339
340    #[snafu(display("Adding field column {} to physical table", name))]
341    AddingFieldColumn {
342        name: String,
343        #[snafu(implicit)]
344        location: Location,
345    },
346
347    #[snafu(display("No field column found"))]
348    NoFieldColumn {
349        #[snafu(implicit)]
350        location: Location,
351    },
352
353    #[snafu(display("Failed to set SKIPPING index option"))]
354    SetSkippingIndexOption {
355        source: datatypes::error::Error,
356        #[snafu(implicit)]
357        location: Location,
358    },
359
360    #[snafu(display(
361        "Failed to create default value for column {} of region {}",
362        column,
363        region_id
364    ))]
365    CreateDefault {
366        region_id: RegionId,
367        column: String,
368        source: datatypes::error::Error,
369        #[snafu(implicit)]
370        location: Location,
371    },
372
373    #[snafu(display("Unexpected request: {}", reason))]
374    UnexpectedRequest {
375        reason: String,
376        #[snafu(implicit)]
377        location: Location,
378    },
379
380    #[snafu(display("Expected metric manifest info, region: {}", region_id))]
381    MetricManifestInfo {
382        region_id: RegionId,
383        #[snafu(implicit)]
384        location: Location,
385    },
386
387    #[snafu(display("Failed to start repeated task: {}", name))]
388    StartRepeatedTask {
389        name: String,
390        source: common_runtime::error::Error,
391        #[snafu(implicit)]
392        location: Location,
393    },
394
395    #[snafu(display("Get value from cache"))]
396    CacheGet {
397        source: Arc<Error>,
398        #[snafu(implicit)]
399        location: Location,
400    },
401}
402
403pub type Result<T, E = Error> = std::result::Result<T, E>;
404
405impl ErrorExt for Error {
406    fn status_code(&self) -> StatusCode {
407        use Error::*;
408
409        match self {
410            InternalColumnOccupied { .. }
411            | MissingRegionOption { .. }
412            | ConflictRegionOption { .. }
413            | ColumnTypeMismatch { .. }
414            | TableIdCountMismatch { .. }
415            | PhysicalRegionBusy { .. }
416            | MultipleFieldColumn { .. }
417            | NoFieldColumn { .. }
418            | AddingFieldColumn { .. }
419            | ParseRegionOptions { .. }
420            | UnexpectedRequest { .. }
421            | UnsupportedAlterKind { .. }
422            | UnsupportedRemapManifestsRequest { .. }
423            | UnsupportedSyncRegionFromRequest { .. }
424            | InvalidRequest { .. }
425            | CreateDefault { .. } => StatusCode::InvalidArguments,
426
427            ForbiddenPhysicalAlter { .. }
428            | ForbiddenPhysicalWrite { .. }
429            | UnsupportedRegionRequest { .. }
430            | MissingFiles { .. } => StatusCode::Unsupported,
431
432            DeserializeColumnMetadata { .. }
433            | SerializeColumnMetadata { .. }
434            | DecodeColumnValue { .. }
435            | ParseRegionId { .. }
436            | InvalidMetadata { .. }
437            | SetSkippingIndexOption { .. }
438            | SerializeRegionManifestInfo { .. }
439            | NoOpenRegionResult { .. } => StatusCode::Unexpected,
440
441            PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
442                StatusCode::RegionNotFound
443            }
444
445            ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
446
447            CreateMitoRegion { source, .. }
448            | OpenMitoRegion { source, .. }
449            | CleanUpMitoRegion { source, .. }
450            | CloseMitoRegion { source, .. }
451            | MitoReadOperation { source, .. }
452            | MitoWriteOperation { source, .. }
453            | MitoFlushOperation { source, .. }
454            | MitoSyncOperation { source, .. }
455            | MitoEnterStagingOperation { source, .. }
456            | BatchOpenMitoRegion { source, .. }
457            | BatchCatchupMitoRegion { source, .. }
458            | MitoCopyRegionFromOperation { source, .. }
459            | MitoEditRegion { source, .. } => source.status_code(),
460
461            EncodePrimaryKey { source, .. } => source.status_code(),
462
463            CollectRecordBatchStream { source, .. } => source.status_code(),
464
465            StartRepeatedTask { source, .. } => source.status_code(),
466
467            MetricManifestInfo { .. } => StatusCode::Internal,
468
469            CacheGet { source, .. } => source.status_code(),
470        }
471    }
472
473    fn as_any(&self) -> &dyn Any {
474        self
475    }
476
477    fn retry_hint(&self) -> RetryHint {
478        use Error::*;
479
480        match self {
481            CreateMitoRegion { source, .. }
482            | OpenMitoRegion { source, .. }
483            | CleanUpMitoRegion { source, .. }
484            | BatchOpenMitoRegion { source, .. }
485            | BatchCatchupMitoRegion { source, .. }
486            | CloseMitoRegion { source, .. }
487            | MitoReadOperation { source, .. }
488            | MitoWriteOperation { source, .. }
489            | MitoFlushOperation { source, .. }
490            | MitoSyncOperation { source, .. }
491            | MitoEnterStagingOperation { source, .. }
492            | MitoCopyRegionFromOperation { source, .. }
493            | MitoEditRegion { source, .. } => source.retry_hint(),
494
495            EncodePrimaryKey { source, .. } => source.retry_hint(),
496            CollectRecordBatchStream { source, .. } => source.retry_hint(),
497            StartRepeatedTask { source, .. } => source.retry_hint(),
498            CacheGet { source, .. } => source.retry_hint(),
499
500            _ => RetryHint::NonRetryable,
501        }
502    }
503}