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 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}