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("No open region result for region {}", region_id))]
54    NoOpenRegionResult {
55        region_id: RegionId,
56        #[snafu(implicit)]
57        location: Location,
58    },
59
60    #[snafu(display("Failed to close mito region, region id: {}", region_id))]
61    CloseMitoRegion {
62        region_id: RegionId,
63        source: BoxedError,
64        #[snafu(implicit)]
65        location: Location,
66    },
67
68    #[snafu(display("Failed to deserialize column metadata from {}", raw))]
69    DeserializeColumnMetadata {
70        raw: String,
71        #[snafu(source)]
72        error: serde_json::Error,
73        #[snafu(implicit)]
74        location: Location,
75    },
76
77    #[snafu(display("Failed to serialize column metadata"))]
78    SerializeColumnMetadata {
79        #[snafu(source)]
80        error: serde_json::Error,
81        #[snafu(implicit)]
82        location: Location,
83    },
84
85    #[snafu(display("Failed to serialize region manifest info"))]
86    SerializeRegionManifestInfo {
87        #[snafu(source)]
88        error: serde_json::Error,
89        #[snafu(implicit)]
90        location: Location,
91    },
92
93    #[snafu(display("Failed to decode base64 column value"))]
94    DecodeColumnValue {
95        #[snafu(source)]
96        error: base64::DecodeError,
97        #[snafu(implicit)]
98        location: Location,
99    },
100
101    #[snafu(display("Failed to parse region id from {}", raw))]
102    ParseRegionId {
103        raw: String,
104        #[snafu(source)]
105        error: <u64 as std::str::FromStr>::Err,
106        #[snafu(implicit)]
107        location: Location,
108    },
109
110    #[snafu(display("Failed to parse region options: {}", reason))]
111    ParseRegionOptions {
112        reason: String,
113        #[snafu(implicit)]
114        location: Location,
115    },
116
117    #[snafu(display("Mito read operation fails"))]
118    MitoReadOperation {
119        source: BoxedError,
120        #[snafu(implicit)]
121        location: Location,
122    },
123
124    #[snafu(display("Failed to encode primary key"))]
125    EncodePrimaryKey {
126        source: mito_codec::error::Error,
127        #[snafu(implicit)]
128        location: Location,
129    },
130
131    #[snafu(display("Mito write operation fails"))]
132    MitoWriteOperation {
133        source: BoxedError,
134        #[snafu(implicit)]
135        location: Location,
136    },
137
138    #[snafu(display("Mito flush operation fails"))]
139    MitoFlushOperation {
140        source: BoxedError,
141        #[snafu(implicit)]
142        location: Location,
143    },
144
145    #[snafu(display("Mito delete operation fails"))]
146    MitoDeleteOperation {
147        source: BoxedError,
148        #[snafu(implicit)]
149        location: Location,
150    },
151
152    #[snafu(display("Mito catchup operation fails"))]
153    MitoCatchupOperation {
154        source: BoxedError,
155        #[snafu(implicit)]
156        location: Location,
157    },
158
159    #[snafu(display("Mito sync operation fails"))]
160    MitoSyncOperation {
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 alter kind: {}", kind))]
253    UnsupportedAlterKind {
254        kind: String,
255        #[snafu(implicit)]
256        location: Location,
257    },
258
259    #[snafu(display("Multiple field column found: {} and {}", previous, current))]
260    MultipleFieldColumn {
261        previous: String,
262        current: String,
263        #[snafu(implicit)]
264        location: Location,
265    },
266
267    #[snafu(display("Adding field column {} to physical table", name))]
268    AddingFieldColumn {
269        name: String,
270        #[snafu(implicit)]
271        location: Location,
272    },
273
274    #[snafu(display("No field column found"))]
275    NoFieldColumn {
276        #[snafu(implicit)]
277        location: Location,
278    },
279
280    #[snafu(display("Failed to set SKIPPING index option"))]
281    SetSkippingIndexOption {
282        source: datatypes::error::Error,
283        #[snafu(implicit)]
284        location: Location,
285    },
286
287    #[snafu(display("Unexpected request: {}", reason))]
288    UnexpectedRequest {
289        reason: String,
290        #[snafu(implicit)]
291        location: Location,
292    },
293
294    #[snafu(display("Expected metric manifest info, region: {}", region_id))]
295    MetricManifestInfo {
296        region_id: RegionId,
297        #[snafu(implicit)]
298        location: Location,
299    },
300
301    #[snafu(display("Failed to start repeated task: {}", name))]
302    StartRepeatedTask {
303        name: String,
304        source: common_runtime::error::Error,
305        #[snafu(implicit)]
306        location: Location,
307    },
308
309    #[snafu(display("Get value from cache"))]
310    CacheGet {
311        source: Arc<Error>,
312        #[snafu(implicit)]
313        location: Location,
314    },
315}
316
317pub type Result<T, E = Error> = std::result::Result<T, E>;
318
319impl ErrorExt for Error {
320    fn status_code(&self) -> StatusCode {
321        use Error::*;
322
323        match self {
324            InternalColumnOccupied { .. }
325            | MissingRegionOption { .. }
326            | ConflictRegionOption { .. }
327            | ColumnTypeMismatch { .. }
328            | PhysicalRegionBusy { .. }
329            | MultipleFieldColumn { .. }
330            | NoFieldColumn { .. }
331            | AddingFieldColumn { .. }
332            | ParseRegionOptions { .. }
333            | UnexpectedRequest { .. }
334            | UnsupportedAlterKind { .. } => StatusCode::InvalidArguments,
335
336            ForbiddenPhysicalAlter { .. } | UnsupportedRegionRequest { .. } => {
337                StatusCode::Unsupported
338            }
339
340            DeserializeColumnMetadata { .. }
341            | SerializeColumnMetadata { .. }
342            | DecodeColumnValue { .. }
343            | ParseRegionId { .. }
344            | InvalidMetadata { .. }
345            | SetSkippingIndexOption { .. }
346            | SerializeRegionManifestInfo { .. }
347            | NoOpenRegionResult { .. } => StatusCode::Unexpected,
348
349            PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
350                StatusCode::RegionNotFound
351            }
352
353            ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
354
355            CreateMitoRegion { source, .. }
356            | OpenMitoRegion { source, .. }
357            | CloseMitoRegion { source, .. }
358            | MitoReadOperation { source, .. }
359            | MitoWriteOperation { source, .. }
360            | MitoCatchupOperation { source, .. }
361            | MitoFlushOperation { source, .. }
362            | MitoDeleteOperation { source, .. }
363            | MitoSyncOperation { source, .. }
364            | BatchOpenMitoRegion { source, .. } => source.status_code(),
365
366            EncodePrimaryKey { source, .. } => source.status_code(),
367
368            CollectRecordBatchStream { source, .. } => source.status_code(),
369
370            StartRepeatedTask { source, .. } => source.status_code(),
371
372            MetricManifestInfo { .. } => StatusCode::Internal,
373
374            CacheGet { source, .. } => source.status_code(),
375        }
376    }
377
378    fn as_any(&self) -> &dyn Any {
379        self
380    }
381}