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