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