datanode/
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::define_into_tonic_status;
19use common_error::ext::{BoxedError, ErrorExt};
20use common_error::status_code::StatusCode;
21use common_macro::stack_trace_debug;
22use snafu::{Location, Snafu};
23use store_api::storage::RegionId;
24use table::error::Error as TableError;
25use tokio::time::error::Elapsed;
26
27/// Business error of datanode.
28#[derive(Snafu)]
29#[snafu(visibility(pub))]
30#[stack_trace_debug]
31pub enum Error {
32    #[snafu(display("Failed to execute async task"))]
33    AsyncTaskExecute {
34        #[snafu(implicit)]
35        location: Location,
36        source: Arc<Error>,
37    },
38
39    #[snafu(display("Failed to watch change"))]
40    WatchAsyncTaskChange {
41        #[snafu(implicit)]
42        location: Location,
43        #[snafu(source)]
44        error: tokio::sync::watch::error::RecvError,
45    },
46
47    #[snafu(display("Failed to handle heartbeat response"))]
48    HandleHeartbeatResponse {
49        #[snafu(implicit)]
50        location: Location,
51        source: common_meta::error::Error,
52    },
53
54    #[snafu(display("Failed to get info from meta server"))]
55    GetMetadata {
56        #[snafu(implicit)]
57        location: Location,
58        source: common_meta::error::Error,
59    },
60
61    #[snafu(display("Failed to execute logical plan"))]
62    ExecuteLogicalPlan {
63        #[snafu(implicit)]
64        location: Location,
65        source: query::error::Error,
66    },
67
68    #[snafu(display("Failed to create plan decoder"))]
69    NewPlanDecoder {
70        #[snafu(implicit)]
71        location: Location,
72        source: query::error::Error,
73    },
74
75    #[snafu(display("Failed to decode logical plan"))]
76    DecodeLogicalPlan {
77        #[snafu(implicit)]
78        location: Location,
79        source: common_query::error::Error,
80    },
81
82    #[snafu(display("Schema not found: {}", name))]
83    SchemaNotFound {
84        name: String,
85        #[snafu(implicit)]
86        location: Location,
87    },
88
89    #[snafu(display("Missing timestamp column in request"))]
90    MissingTimestampColumn {
91        #[snafu(implicit)]
92        location: Location,
93    },
94
95    #[snafu(display("Failed to delete value from table: {}", table_name))]
96    Delete {
97        table_name: String,
98        #[snafu(implicit)]
99        location: Location,
100        source: TableError,
101    },
102
103    #[snafu(display("Failed to start server"))]
104    StartServer {
105        #[snafu(implicit)]
106        location: Location,
107        source: servers::error::Error,
108    },
109
110    #[snafu(display("Failed to parse address {}", addr))]
111    ParseAddr {
112        addr: String,
113        #[snafu(source)]
114        error: std::net::AddrParseError,
115    },
116
117    #[snafu(display("Failed to create directory {}", dir))]
118    CreateDir {
119        dir: String,
120        #[snafu(source)]
121        error: std::io::Error,
122    },
123
124    #[snafu(display("Failed to remove directory {}", dir))]
125    RemoveDir {
126        dir: String,
127        #[snafu(source)]
128        error: std::io::Error,
129    },
130
131    #[snafu(display("Failed to open log store"))]
132    OpenLogStore {
133        #[snafu(implicit)]
134        location: Location,
135        source: Box<log_store::error::Error>,
136    },
137
138    #[snafu(display("Invalid SQL, error: {}", msg))]
139    InvalidSql { msg: String },
140
141    #[snafu(display("Illegal primary keys definition: {}", msg))]
142    IllegalPrimaryKeysDef {
143        msg: String,
144        #[snafu(implicit)]
145        location: Location,
146    },
147
148    #[snafu(display("Schema {} already exists", name))]
149    SchemaExists {
150        name: String,
151        #[snafu(implicit)]
152        location: Location,
153    },
154
155    #[snafu(display("Failed to initialize meta client"))]
156    MetaClientInit {
157        #[snafu(implicit)]
158        location: Location,
159        source: meta_client::error::Error,
160    },
161
162    #[snafu(display("Missing node id in Datanode config"))]
163    MissingNodeId {
164        #[snafu(implicit)]
165        location: Location,
166    },
167
168    #[snafu(display("Failed to build datanode"))]
169    BuildDatanode {
170        #[snafu(implicit)]
171        location: Location,
172        source: BoxedError,
173    },
174
175    #[snafu(display("Failed to build http client"))]
176    BuildHttpClient {
177        #[snafu(implicit)]
178        location: Location,
179        #[snafu(source)]
180        error: reqwest::Error,
181    },
182
183    #[snafu(display("Missing required field: {}", name))]
184    MissingRequiredField {
185        name: String,
186        #[snafu(implicit)]
187        location: Location,
188    },
189
190    #[snafu(display(
191        "No valid default value can be built automatically, column: {}",
192        column,
193    ))]
194    ColumnNoneDefaultValue {
195        column: String,
196        #[snafu(implicit)]
197        location: Location,
198    },
199
200    #[snafu(display("Failed to shutdown server"))]
201    ShutdownServer {
202        #[snafu(implicit)]
203        location: Location,
204        #[snafu(source)]
205        source: servers::error::Error,
206    },
207
208    #[snafu(display("Failed to shutdown instance"))]
209    ShutdownInstance {
210        #[snafu(implicit)]
211        location: Location,
212        #[snafu(source)]
213        source: BoxedError,
214    },
215
216    #[snafu(display("Payload not exist"))]
217    PayloadNotExist {
218        #[snafu(implicit)]
219        location: Location,
220    },
221
222    #[snafu(display("Unexpected, violated: {}", violated))]
223    Unexpected {
224        violated: String,
225        #[snafu(implicit)]
226        location: Location,
227    },
228
229    #[snafu(display("Failed to handle request for region {}", region_id))]
230    HandleRegionRequest {
231        region_id: RegionId,
232        #[snafu(implicit)]
233        location: Location,
234        source: BoxedError,
235    },
236
237    #[snafu(display("Failed to open batch regions"))]
238    HandleBatchOpenRequest {
239        #[snafu(implicit)]
240        location: Location,
241        source: BoxedError,
242    },
243
244    #[snafu(display("Failed to handle batch ddl request, ddl_type: {}", ddl_type))]
245    HandleBatchDdlRequest {
246        #[snafu(implicit)]
247        location: Location,
248        source: BoxedError,
249        ddl_type: String,
250    },
251
252    #[snafu(display("RegionId {} not found", region_id))]
253    RegionNotFound {
254        region_id: RegionId,
255        #[snafu(implicit)]
256        location: Location,
257    },
258
259    #[snafu(display("Region {} not ready", region_id))]
260    RegionNotReady {
261        region_id: RegionId,
262        #[snafu(implicit)]
263        location: Location,
264    },
265
266    #[snafu(display("Region {} is busy", region_id))]
267    RegionBusy {
268        region_id: RegionId,
269        #[snafu(implicit)]
270        location: Location,
271    },
272
273    #[snafu(display("Region engine {} is not registered", name))]
274    RegionEngineNotFound {
275        name: String,
276        #[snafu(implicit)]
277        location: Location,
278    },
279
280    #[snafu(display("Unsupported output type, expected: {}", expected))]
281    UnsupportedOutput {
282        expected: String,
283        #[snafu(implicit)]
284        location: Location,
285    },
286
287    #[snafu(display("Failed to build region requests"))]
288    BuildRegionRequests {
289        #[snafu(implicit)]
290        location: Location,
291        source: store_api::metadata::MetadataError,
292    },
293
294    #[snafu(display("Failed to stop region engine {}", name))]
295    StopRegionEngine {
296        name: String,
297        #[snafu(implicit)]
298        location: Location,
299        source: BoxedError,
300    },
301
302    #[snafu(display(
303        "Failed to find logical regions in physical region {}",
304        physical_region_id
305    ))]
306    FindLogicalRegions {
307        physical_region_id: RegionId,
308        source: metric_engine::error::Error,
309        #[snafu(implicit)]
310        location: Location,
311    },
312
313    #[snafu(display("Failed to build mito engine"))]
314    BuildMitoEngine {
315        source: mito2::error::Error,
316        #[snafu(implicit)]
317        location: Location,
318    },
319
320    #[snafu(display("Failed to build metric engine"))]
321    BuildMetricEngine {
322        source: metric_engine::error::Error,
323        #[snafu(implicit)]
324        location: Location,
325    },
326
327    #[snafu(display("Failed to run gc for region {}", region_id))]
328    GcMitoEngine {
329        region_id: RegionId,
330        source: mito2::error::Error,
331        #[snafu(implicit)]
332        location: Location,
333    },
334
335    #[snafu(display("Failed to list SST entries from storage"))]
336    ListStorageSsts {
337        #[snafu(implicit)]
338        location: Location,
339        source: mito2::error::Error,
340    },
341
342    #[snafu(display("Failed to serialize options to TOML"))]
343    TomlFormat {
344        #[snafu(implicit)]
345        location: Location,
346        #[snafu(source(from(common_config::error::Error, Box::new)))]
347        source: Box<common_config::error::Error>,
348    },
349
350    #[snafu(display(
351        "Failed to get region metadata from engine {} for region_id {}",
352        engine,
353        region_id,
354    ))]
355    GetRegionMetadata {
356        engine: String,
357        region_id: RegionId,
358        #[snafu(implicit)]
359        location: Location,
360        source: BoxedError,
361    },
362
363    #[snafu(display("DataFusion"))]
364    DataFusion {
365        #[snafu(source)]
366        error: datafusion::error::DataFusionError,
367        #[snafu(implicit)]
368        location: Location,
369    },
370
371    #[snafu(display("Failed to acquire permit, source closed"))]
372    ConcurrentQueryLimiterClosed {
373        #[snafu(source)]
374        error: tokio::sync::AcquireError,
375        #[snafu(implicit)]
376        location: Location,
377    },
378
379    #[snafu(display("Failed to acquire permit under timeouts"))]
380    ConcurrentQueryLimiterTimeout {
381        #[snafu(source)]
382        error: Elapsed,
383        #[snafu(implicit)]
384        location: Location,
385    },
386
387    #[snafu(display("Cache not found in registry"))]
388    MissingCache {
389        #[snafu(implicit)]
390        location: Location,
391    },
392
393    #[snafu(display("Failed to serialize json"))]
394    SerializeJson {
395        #[snafu(source)]
396        error: serde_json::Error,
397        #[snafu(implicit)]
398        location: Location,
399    },
400
401    #[snafu(display("Failed object store operation"))]
402    ObjectStore {
403        source: object_store::error::Error,
404        #[snafu(implicit)]
405        location: Location,
406    },
407
408    #[snafu(display("Not yet implemented: {what}"))]
409    NotYetImplemented { what: String },
410}
411
412pub type Result<T> = std::result::Result<T, Error>;
413
414impl ErrorExt for Error {
415    fn status_code(&self) -> StatusCode {
416        use Error::*;
417        match self {
418            NewPlanDecoder { source, .. } | ExecuteLogicalPlan { source, .. } => {
419                source.status_code()
420            }
421
422            BuildRegionRequests { source, .. } => source.status_code(),
423            HandleHeartbeatResponse { source, .. } | GetMetadata { source, .. } => {
424                source.status_code()
425            }
426
427            DecodeLogicalPlan { source, .. } => source.status_code(),
428
429            Delete { source, .. } => source.status_code(),
430
431            InvalidSql { .. }
432            | IllegalPrimaryKeysDef { .. }
433            | MissingTimestampColumn { .. }
434            | SchemaNotFound { .. }
435            | SchemaExists { .. }
436            | MissingNodeId { .. }
437            | ColumnNoneDefaultValue { .. }
438            | MissingRequiredField { .. }
439            | RegionEngineNotFound { .. }
440            | ParseAddr { .. }
441            | TomlFormat { .. }
442            | BuildDatanode { .. } => StatusCode::InvalidArguments,
443
444            PayloadNotExist { .. }
445            | Unexpected { .. }
446            | WatchAsyncTaskChange { .. }
447            | BuildHttpClient { .. } => StatusCode::Unexpected,
448
449            AsyncTaskExecute { source, .. } => source.status_code(),
450
451            CreateDir { .. } | RemoveDir { .. } | ShutdownInstance { .. } | DataFusion { .. } => {
452                StatusCode::Internal
453            }
454
455            RegionNotFound { .. } => StatusCode::RegionNotFound,
456            RegionNotReady { .. } => StatusCode::RegionNotReady,
457            RegionBusy { .. } => StatusCode::RegionBusy,
458
459            StartServer { source, .. } | ShutdownServer { source, .. } => source.status_code(),
460
461            OpenLogStore { source, .. } => source.status_code(),
462            MetaClientInit { source, .. } => source.status_code(),
463            UnsupportedOutput { .. } | NotYetImplemented { .. } => StatusCode::Unsupported,
464            HandleRegionRequest { source, .. }
465            | GetRegionMetadata { source, .. }
466            | HandleBatchOpenRequest { source, .. }
467            | HandleBatchDdlRequest { source, .. } => source.status_code(),
468            StopRegionEngine { source, .. } => source.status_code(),
469
470            FindLogicalRegions { source, .. } => source.status_code(),
471            BuildMitoEngine { source, .. } | GcMitoEngine { source, .. } => source.status_code(),
472            BuildMetricEngine { source, .. } => source.status_code(),
473            ListStorageSsts { source, .. } => source.status_code(),
474            ConcurrentQueryLimiterClosed { .. } | ConcurrentQueryLimiterTimeout { .. } => {
475                StatusCode::RegionBusy
476            }
477            MissingCache { .. } => StatusCode::Internal,
478            SerializeJson { .. } => StatusCode::Internal,
479
480            ObjectStore { source, .. } => source.status_code(),
481        }
482    }
483
484    fn as_any(&self) -> &dyn Any {
485        self
486    }
487}
488
489define_into_tonic_status!(Error);