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::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("Failed to encode primary key"))]
132    EncodePrimaryKey {
133        source: mito_codec::error::Error,
134        #[snafu(implicit)]
135        location: Location,
136    },
137
138    #[snafu(display("Mito write operation fails"))]
139    MitoWriteOperation {
140        source: BoxedError,
141        #[snafu(implicit)]
142        location: Location,
143    },
144
145    #[snafu(display("Mito flush operation fails"))]
146    MitoFlushOperation {
147        source: BoxedError,
148        #[snafu(implicit)]
149        location: Location,
150    },
151
152    #[snafu(display("Mito sync operation fails"))]
153    MitoSyncOperation {
154        source: BoxedError,
155        #[snafu(implicit)]
156        location: Location,
157    },
158
159    #[snafu(display("Mito enter staging operation fails"))]
160    MitoEnterStagingOperation {
161        source: BoxedError,
162        #[snafu(implicit)]
163        location: Location,
164    },
165
166    #[snafu(display("Failed to collect record batch stream"))]
167    CollectRecordBatchStream {
168        source: common_recordbatch::error::Error,
169        #[snafu(implicit)]
170        location: Location,
171    },
172
173    #[snafu(display("Internal column {} is reserved", column))]
174    InternalColumnOccupied {
175        column: String,
176        #[snafu(implicit)]
177        location: Location,
178    },
179
180    #[snafu(display("Required table option is missing"))]
181    MissingRegionOption {
182        #[snafu(implicit)]
183        location: Location,
184    },
185
186    #[snafu(display("Region options are conflicted"))]
187    ConflictRegionOption {
188        #[snafu(implicit)]
189        location: Location,
190    },
191
192    #[snafu(display("Physical region {} not found", region_id))]
193    PhysicalRegionNotFound {
194        region_id: RegionId,
195        #[snafu(implicit)]
196        location: Location,
197    },
198
199    #[snafu(display("Logical region {} not found", region_id))]
200    LogicalRegionNotFound {
201        region_id: RegionId,
202        #[snafu(implicit)]
203        location: Location,
204    },
205
206    #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
207    ColumnTypeMismatch {
208        expect: ConcreteDataType,
209        actual: ConcreteDataType,
210        #[snafu(implicit)]
211        location: Location,
212    },
213
214    #[snafu(display("Column {} not found in logical region {}", name, region_id))]
215    ColumnNotFound {
216        name: String,
217        region_id: RegionId,
218        #[snafu(implicit)]
219        location: Location,
220    },
221
222    #[snafu(display("Alter request to physical region is forbidden"))]
223    ForbiddenPhysicalAlter {
224        #[snafu(implicit)]
225        location: Location,
226    },
227
228    #[snafu(display("Invalid region metadata"))]
229    InvalidMetadata {
230        source: store_api::metadata::MetadataError,
231        #[snafu(implicit)]
232        location: Location,
233    },
234
235    #[snafu(display(
236        "Physical region {} is busy, there are still some logical regions using it",
237        region_id
238    ))]
239    PhysicalRegionBusy {
240        region_id: RegionId,
241        #[snafu(implicit)]
242        location: Location,
243    },
244
245    #[snafu(display("Unsupported region request: {}", request))]
246    UnsupportedRegionRequest {
247        request: Box<RegionRequest>,
248        #[snafu(implicit)]
249        location: Location,
250    },
251
252    #[snafu(display("Unsupported remap manifests request for region {}", region_id))]
253    UnsupportedRemapManifestsRequest {
254        region_id: RegionId,
255        #[snafu(implicit)]
256        location: Location,
257    },
258
259    #[snafu(display("Unsupported alter kind: {}", kind))]
260    UnsupportedAlterKind {
261        kind: String,
262        #[snafu(implicit)]
263        location: Location,
264    },
265
266    #[snafu(display("Multiple field column found: {} and {}", previous, current))]
267    MultipleFieldColumn {
268        previous: String,
269        current: String,
270        #[snafu(implicit)]
271        location: Location,
272    },
273
274    #[snafu(display("Adding field column {} to physical table", name))]
275    AddingFieldColumn {
276        name: String,
277        #[snafu(implicit)]
278        location: Location,
279    },
280
281    #[snafu(display("No field column found"))]
282    NoFieldColumn {
283        #[snafu(implicit)]
284        location: Location,
285    },
286
287    #[snafu(display("Failed to set SKIPPING index option"))]
288    SetSkippingIndexOption {
289        source: datatypes::error::Error,
290        #[snafu(implicit)]
291        location: Location,
292    },
293
294    #[snafu(display("Unexpected request: {}", reason))]
295    UnexpectedRequest {
296        reason: String,
297        #[snafu(implicit)]
298        location: Location,
299    },
300
301    #[snafu(display("Expected metric manifest info, region: {}", region_id))]
302    MetricManifestInfo {
303        region_id: RegionId,
304        #[snafu(implicit)]
305        location: Location,
306    },
307
308    #[snafu(display("Failed to start repeated task: {}", name))]
309    StartRepeatedTask {
310        name: String,
311        source: common_runtime::error::Error,
312        #[snafu(implicit)]
313        location: Location,
314    },
315
316    #[snafu(display("Get value from cache"))]
317    CacheGet {
318        source: Arc<Error>,
319        #[snafu(implicit)]
320        location: Location,
321    },
322}
323
324pub type Result<T, E = Error> = std::result::Result<T, E>;
325
326impl ErrorExt for Error {
327    fn status_code(&self) -> StatusCode {
328        use Error::*;
329
330        match self {
331            InternalColumnOccupied { .. }
332            | MissingRegionOption { .. }
333            | ConflictRegionOption { .. }
334            | ColumnTypeMismatch { .. }
335            | PhysicalRegionBusy { .. }
336            | MultipleFieldColumn { .. }
337            | NoFieldColumn { .. }
338            | AddingFieldColumn { .. }
339            | ParseRegionOptions { .. }
340            | UnexpectedRequest { .. }
341            | UnsupportedAlterKind { .. }
342            | UnsupportedRemapManifestsRequest { .. } => StatusCode::InvalidArguments,
343
344            ForbiddenPhysicalAlter { .. } | UnsupportedRegionRequest { .. } => {
345                StatusCode::Unsupported
346            }
347
348            DeserializeColumnMetadata { .. }
349            | SerializeColumnMetadata { .. }
350            | DecodeColumnValue { .. }
351            | ParseRegionId { .. }
352            | InvalidMetadata { .. }
353            | SetSkippingIndexOption { .. }
354            | SerializeRegionManifestInfo { .. }
355            | NoOpenRegionResult { .. } => StatusCode::Unexpected,
356
357            PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
358                StatusCode::RegionNotFound
359            }
360
361            ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
362
363            CreateMitoRegion { source, .. }
364            | OpenMitoRegion { source, .. }
365            | CloseMitoRegion { source, .. }
366            | MitoReadOperation { source, .. }
367            | MitoWriteOperation { source, .. }
368            | MitoFlushOperation { source, .. }
369            | MitoSyncOperation { source, .. }
370            | MitoEnterStagingOperation { source, .. }
371            | BatchOpenMitoRegion { source, .. }
372            | BatchCatchupMitoRegion { source, .. } => source.status_code(),
373
374            EncodePrimaryKey { source, .. } => source.status_code(),
375
376            CollectRecordBatchStream { source, .. } => source.status_code(),
377
378            StartRepeatedTask { source, .. } => source.status_code(),
379
380            MetricManifestInfo { .. } => StatusCode::Internal,
381
382            CacheGet { source, .. } => source.status_code(),
383        }
384    }
385
386    fn as_any(&self) -> &dyn Any {
387        self
388    }
389}