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;
16
17use common_error::ext::{BoxedError, ErrorExt};
18use common_error::status_code::StatusCode;
19use common_macro::stack_trace_debug;
20use datatypes::prelude::ConcreteDataType;
21use snafu::{Location, Snafu};
22use store_api::region_request::RegionRequest;
23use store_api::storage::RegionId;
24
25#[derive(Snafu)]
26#[snafu(visibility(pub))]
27#[stack_trace_debug]
28pub enum Error {
29    #[snafu(display("Failed to create mito region, region type: {}", region_type))]
30    CreateMitoRegion {
31        region_type: String,
32        source: BoxedError,
33        #[snafu(implicit)]
34        location: Location,
35    },
36
37    #[snafu(display("Failed to open mito region, region type: {}", region_type))]
38    OpenMitoRegion {
39        region_type: String,
40        source: BoxedError,
41        #[snafu(implicit)]
42        location: Location,
43    },
44
45    #[snafu(display("Failed to batch open mito region"))]
46    BatchOpenMitoRegion {
47        source: BoxedError,
48        #[snafu(implicit)]
49        location: Location,
50    },
51
52    #[snafu(display("No open region result for region {}", region_id))]
53    NoOpenRegionResult {
54        region_id: RegionId,
55        #[snafu(implicit)]
56        location: Location,
57    },
58
59    #[snafu(display("Failed to close mito region, region id: {}", region_id))]
60    CloseMitoRegion {
61        region_id: RegionId,
62        source: BoxedError,
63        #[snafu(implicit)]
64        location: Location,
65    },
66
67    #[snafu(display("Failed to deserialize column metadata from {}", raw))]
68    DeserializeColumnMetadata {
69        raw: String,
70        #[snafu(source)]
71        error: serde_json::Error,
72        #[snafu(implicit)]
73        location: Location,
74    },
75
76    #[snafu(display("Failed to serialize column metadata"))]
77    SerializeColumnMetadata {
78        #[snafu(source)]
79        error: serde_json::Error,
80        #[snafu(implicit)]
81        location: Location,
82    },
83
84    #[snafu(display("Failed to serialize region manifest info"))]
85    SerializeRegionManifestInfo {
86        #[snafu(source)]
87        error: serde_json::Error,
88        #[snafu(implicit)]
89        location: Location,
90    },
91
92    #[snafu(display("Failed to decode base64 column value"))]
93    DecodeColumnValue {
94        #[snafu(source)]
95        error: base64::DecodeError,
96        #[snafu(implicit)]
97        location: Location,
98    },
99
100    #[snafu(display("Failed to parse region id from {}", raw))]
101    ParseRegionId {
102        raw: String,
103        #[snafu(source)]
104        error: <u64 as std::str::FromStr>::Err,
105        #[snafu(implicit)]
106        location: Location,
107    },
108
109    #[snafu(display("Failed to parse region options: {}", reason))]
110    ParseRegionOptions {
111        reason: String,
112        #[snafu(implicit)]
113        location: Location,
114    },
115
116    #[snafu(display("Mito read operation fails"))]
117    MitoReadOperation {
118        source: BoxedError,
119        #[snafu(implicit)]
120        location: Location,
121    },
122
123    #[snafu(display("Failed to encode primary key"))]
124    EncodePrimaryKey {
125        source: mito_codec::error::Error,
126        #[snafu(implicit)]
127        location: Location,
128    },
129
130    #[snafu(display("Mito write operation fails"))]
131    MitoWriteOperation {
132        source: BoxedError,
133        #[snafu(implicit)]
134        location: Location,
135    },
136
137    #[snafu(display("Mito flush operation fails"))]
138    MitoFlushOperation {
139        source: BoxedError,
140        #[snafu(implicit)]
141        location: Location,
142    },
143
144    #[snafu(display("Mito delete operation fails"))]
145    MitoDeleteOperation {
146        source: BoxedError,
147        #[snafu(implicit)]
148        location: Location,
149    },
150
151    #[snafu(display("Mito catchup operation fails"))]
152    MitoCatchupOperation {
153        source: BoxedError,
154        #[snafu(implicit)]
155        location: Location,
156    },
157
158    #[snafu(display("Mito sync operation fails"))]
159    MitoSyncOperation {
160        source: BoxedError,
161        #[snafu(implicit)]
162        location: Location,
163    },
164
165    #[snafu(display("Failed to collect record batch stream"))]
166    CollectRecordBatchStream {
167        source: common_recordbatch::error::Error,
168        #[snafu(implicit)]
169        location: Location,
170    },
171
172    #[snafu(display("Internal column {} is reserved", column))]
173    InternalColumnOccupied {
174        column: String,
175        #[snafu(implicit)]
176        location: Location,
177    },
178
179    #[snafu(display("Required table option is missing"))]
180    MissingRegionOption {
181        #[snafu(implicit)]
182        location: Location,
183    },
184
185    #[snafu(display("Region options are conflicted"))]
186    ConflictRegionOption {
187        #[snafu(implicit)]
188        location: Location,
189    },
190
191    #[snafu(display("Physical region {} not found", region_id))]
192    PhysicalRegionNotFound {
193        region_id: RegionId,
194        #[snafu(implicit)]
195        location: Location,
196    },
197
198    #[snafu(display("Logical region {} not found", region_id))]
199    LogicalRegionNotFound {
200        region_id: RegionId,
201        #[snafu(implicit)]
202        location: Location,
203    },
204
205    #[snafu(display("Column type mismatch. Expect {:?}, got {:?}", expect, actual))]
206    ColumnTypeMismatch {
207        expect: ConcreteDataType,
208        actual: ConcreteDataType,
209        #[snafu(implicit)]
210        location: Location,
211    },
212
213    #[snafu(display("Column {} not found in logical region {}", name, region_id))]
214    ColumnNotFound {
215        name: String,
216        region_id: RegionId,
217        #[snafu(implicit)]
218        location: Location,
219    },
220
221    #[snafu(display("Alter request to physical region is forbidden"))]
222    ForbiddenPhysicalAlter {
223        #[snafu(implicit)]
224        location: Location,
225    },
226
227    #[snafu(display("Invalid region metadata"))]
228    InvalidMetadata {
229        source: store_api::metadata::MetadataError,
230        #[snafu(implicit)]
231        location: Location,
232    },
233
234    #[snafu(display(
235        "Physical region {} is busy, there are still some logical regions using it",
236        region_id
237    ))]
238    PhysicalRegionBusy {
239        region_id: RegionId,
240        #[snafu(implicit)]
241        location: Location,
242    },
243
244    #[snafu(display("Unsupported region request: {}", request))]
245    UnsupportedRegionRequest {
246        request: Box<RegionRequest>,
247        #[snafu(implicit)]
248        location: Location,
249    },
250
251    #[snafu(display("Unsupported alter kind: {}", kind))]
252    UnsupportedAlterKind {
253        kind: String,
254        #[snafu(implicit)]
255        location: Location,
256    },
257
258    #[snafu(display("Multiple field column found: {} and {}", previous, current))]
259    MultipleFieldColumn {
260        previous: String,
261        current: String,
262        #[snafu(implicit)]
263        location: Location,
264    },
265
266    #[snafu(display("Adding field column {} to physical table", name))]
267    AddingFieldColumn {
268        name: String,
269        #[snafu(implicit)]
270        location: Location,
271    },
272
273    #[snafu(display("No field column found"))]
274    NoFieldColumn {
275        #[snafu(implicit)]
276        location: Location,
277    },
278
279    #[snafu(display("Failed to set SKIPPING index option"))]
280    SetSkippingIndexOption {
281        source: datatypes::error::Error,
282        #[snafu(implicit)]
283        location: Location,
284    },
285
286    #[snafu(display("Unexpected request: {}", reason))]
287    UnexpectedRequest {
288        reason: String,
289        #[snafu(implicit)]
290        location: Location,
291    },
292
293    #[snafu(display("Expected metric manifest info, region: {}", region_id))]
294    MetricManifestInfo {
295        region_id: RegionId,
296        #[snafu(implicit)]
297        location: Location,
298    },
299
300    #[snafu(display("Failed to start repeated task: {}", name))]
301    StartRepeatedTask {
302        name: String,
303        source: common_runtime::error::Error,
304        #[snafu(implicit)]
305        location: Location,
306    },
307}
308
309pub type Result<T, E = Error> = std::result::Result<T, E>;
310
311impl ErrorExt for Error {
312    fn status_code(&self) -> StatusCode {
313        use Error::*;
314
315        match self {
316            InternalColumnOccupied { .. }
317            | MissingRegionOption { .. }
318            | ConflictRegionOption { .. }
319            | ColumnTypeMismatch { .. }
320            | PhysicalRegionBusy { .. }
321            | MultipleFieldColumn { .. }
322            | NoFieldColumn { .. }
323            | AddingFieldColumn { .. }
324            | ParseRegionOptions { .. }
325            | UnexpectedRequest { .. }
326            | UnsupportedAlterKind { .. } => StatusCode::InvalidArguments,
327
328            ForbiddenPhysicalAlter { .. } | UnsupportedRegionRequest { .. } => {
329                StatusCode::Unsupported
330            }
331
332            DeserializeColumnMetadata { .. }
333            | SerializeColumnMetadata { .. }
334            | DecodeColumnValue { .. }
335            | ParseRegionId { .. }
336            | InvalidMetadata { .. }
337            | SetSkippingIndexOption { .. }
338            | SerializeRegionManifestInfo { .. }
339            | NoOpenRegionResult { .. } => StatusCode::Unexpected,
340
341            PhysicalRegionNotFound { .. } | LogicalRegionNotFound { .. } => {
342                StatusCode::RegionNotFound
343            }
344
345            ColumnNotFound { .. } => StatusCode::TableColumnNotFound,
346
347            CreateMitoRegion { source, .. }
348            | OpenMitoRegion { source, .. }
349            | CloseMitoRegion { source, .. }
350            | MitoReadOperation { source, .. }
351            | MitoWriteOperation { source, .. }
352            | MitoCatchupOperation { source, .. }
353            | MitoFlushOperation { source, .. }
354            | MitoDeleteOperation { source, .. }
355            | MitoSyncOperation { source, .. }
356            | BatchOpenMitoRegion { source, .. } => source.status_code(),
357
358            EncodePrimaryKey { source, .. } => source.status_code(),
359
360            CollectRecordBatchStream { source, .. } => source.status_code(),
361
362            StartRepeatedTask { source, .. } => source.status_code(),
363
364            MetricManifestInfo { .. } => StatusCode::Internal,
365        }
366    }
367
368    fn as_any(&self) -> &dyn Any {
369        self
370    }
371}