1use std::any::Any;
16
17use arrow_schema::ArrowError;
18use common_error::ext::{ErrorExt, RetryHint, retry_hint_from_io_error};
19use common_error::status_code::StatusCode;
20use common_macro::stack_trace_debug;
21use datafusion::parquet::errors::ParquetError;
22use object_store::error::retry_hint_from_opendal_error;
23use snafu::{Location, Snafu};
24use url::ParseError;
25
26#[derive(Snafu)]
27#[snafu(visibility(pub))]
28#[stack_trace_debug]
29pub enum Error {
30 #[snafu(display("Unsupported compression type: {}", compression_type))]
31 UnsupportedCompressionType {
32 compression_type: String,
33 #[snafu(implicit)]
34 location: Location,
35 },
36
37 #[snafu(display("Unsupported backend protocol: {}, url: {}", protocol, url))]
38 UnsupportedBackendProtocol {
39 protocol: String,
40 #[snafu(implicit)]
41 location: Location,
42 url: String,
43 },
44
45 #[snafu(display("Unsupported format protocol: {}", format))]
46 UnsupportedFormat {
47 format: String,
48 #[snafu(implicit)]
49 location: Location,
50 },
51
52 #[snafu(display("empty host: {}", url))]
53 EmptyHostPath {
54 url: String,
55 #[snafu(implicit)]
56 location: Location,
57 },
58
59 #[snafu(display("Invalid url: {}", url))]
60 InvalidUrl {
61 url: String,
62 #[snafu(source)]
63 error: ParseError,
64 #[snafu(implicit)]
65 location: Location,
66 },
67
68 #[snafu(display("Failed to build backend"))]
69 BuildBackend {
70 #[snafu(source)]
71 error: object_store::Error,
72 #[snafu(implicit)]
73 location: Location,
74 },
75
76 #[snafu(display("Failed to build orc reader"))]
77 OrcReader {
78 #[snafu(implicit)]
79 location: Location,
80 #[snafu(source)]
81 error: orc_rust::error::OrcError,
82 },
83
84 #[snafu(display("Failed to read object from path: {}", path))]
85 ReadObject {
86 path: String,
87 #[snafu(implicit)]
88 location: Location,
89 #[snafu(source)]
90 error: object_store::Error,
91 },
92
93 #[snafu(display("Failed to write object to path: {}", path))]
94 WriteObject {
95 path: String,
96 #[snafu(implicit)]
97 location: Location,
98 #[snafu(source)]
99 error: object_store::Error,
100 },
101
102 #[snafu(display("Failed to write"))]
103 AsyncWrite {
104 #[snafu(source)]
105 error: std::io::Error,
106 #[snafu(implicit)]
107 location: Location,
108 },
109
110 #[snafu(display("Failed to write record batch"))]
111 WriteRecordBatch {
112 #[snafu(implicit)]
113 location: Location,
114 #[snafu(source)]
115 error: ArrowError,
116 },
117
118 #[snafu(display("Failed to encode record batch"))]
119 EncodeRecordBatch {
120 #[snafu(implicit)]
121 location: Location,
122 #[snafu(source)]
123 error: ParquetError,
124 },
125
126 #[snafu(display("Failed to read record batch"))]
127 ReadRecordBatch {
128 #[snafu(implicit)]
129 location: Location,
130 #[snafu(source)]
131 error: datafusion::error::DataFusionError,
132 },
133
134 #[snafu(display("Failed to read parquet"))]
135 ReadParquetSnafu {
136 #[snafu(implicit)]
137 location: Location,
138 #[snafu(source)]
139 error: datafusion::parquet::errors::ParquetError,
140 },
141
142 #[snafu(display("Failed to convert parquet to schema"))]
143 ParquetToSchema {
144 #[snafu(implicit)]
145 location: Location,
146 #[snafu(source)]
147 error: datafusion::parquet::errors::ParquetError,
148 },
149
150 #[snafu(display("Failed to infer schema from file"))]
151 InferSchema {
152 #[snafu(implicit)]
153 location: Location,
154 #[snafu(source)]
155 error: arrow_schema::ArrowError,
156 },
157
158 #[snafu(display("Failed to list object in path: {}", path))]
159 ListObjects {
160 path: String,
161 #[snafu(implicit)]
162 location: Location,
163 #[snafu(source)]
164 error: object_store::Error,
165 },
166
167 #[snafu(display("Invalid connection: {}", msg))]
168 InvalidConnection {
169 msg: String,
170 #[snafu(implicit)]
171 location: Location,
172 },
173
174 #[snafu(display("Failed to join handle"))]
175 JoinHandle {
176 #[snafu(implicit)]
177 location: Location,
178 #[snafu(source)]
179 error: tokio::task::JoinError,
180 },
181
182 #[snafu(display("Failed to parse format {} with value: {}", key, value))]
183 ParseFormat {
184 key: String,
185 value: String,
186 #[snafu(implicit)]
187 location: Location,
188 },
189
190 #[snafu(display("Failed to merge schema"))]
191 MergeSchema {
192 #[snafu(source)]
193 error: arrow_schema::ArrowError,
194 #[snafu(implicit)]
195 location: Location,
196 },
197
198 #[snafu(display("Failed to write parquet file, path: {}", path))]
199 WriteParquet {
200 path: String,
201 #[snafu(implicit)]
202 location: Location,
203 #[snafu(source)]
204 error: parquet::errors::ParquetError,
205 },
206
207 #[snafu(transparent)]
208 DataFusion {
209 #[snafu(implicit)]
210 location: Location,
211 #[snafu(source)]
212 error: datafusion::error::DataFusionError,
213 },
214}
215
216pub type Result<T> = std::result::Result<T, Error>;
217
218impl ErrorExt for Error {
219 fn status_code(&self) -> StatusCode {
220 use Error::*;
221 match self {
222 BuildBackend { .. }
223 | ListObjects { .. }
224 | ReadObject { .. }
225 | WriteObject { .. }
226 | AsyncWrite { .. }
227 | WriteParquet { .. } => StatusCode::StorageUnavailable,
228
229 UnsupportedBackendProtocol { .. }
230 | UnsupportedCompressionType { .. }
231 | UnsupportedFormat { .. }
232 | InvalidConnection { .. }
233 | InvalidUrl { .. }
234 | EmptyHostPath { .. }
235 | InferSchema { .. }
236 | ReadParquetSnafu { .. }
237 | ParquetToSchema { .. }
238 | ParseFormat { .. }
239 | MergeSchema { .. } => StatusCode::InvalidArguments,
240
241 JoinHandle { .. }
242 | ReadRecordBatch { .. }
243 | WriteRecordBatch { .. }
244 | EncodeRecordBatch { .. }
245 | OrcReader { .. } => StatusCode::Unexpected,
246
247 DataFusion { .. } => StatusCode::Internal,
248 }
249 }
250
251 fn as_any(&self) -> &dyn Any {
252 self
253 }
254
255 fn retry_hint(&self) -> RetryHint {
256 use Error::*;
257
258 match self {
259 BuildBackend { error, .. }
260 | ListObjects { error, .. }
261 | ReadObject { error, .. }
262 | WriteObject { error, .. } => retry_hint_from_opendal_error(error),
263 AsyncWrite { error, .. } => retry_hint_from_io_error(error),
264 WriteParquet { .. } => RetryHint::Retryable,
265 _ => RetryHint::NonRetryable,
266 }
267 }
268}