quickwit_aws/
error.rs

1// Copyright (C) 2021 Quickwit, Inc.
2//
3// Quickwit is offered under the AGPL v3.0 and as commercial software.
4// For commercial licensing, contact us at hello@quickwit.io.
5//
6// AGPL:
7// This program is free software: you can redistribute it and/or modify
8// it under the terms of the GNU Affero General Public License as
9// published by the Free Software Foundation, either version 3 of the
10// License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU Affero General Public License for more details.
16//
17// You should have received a copy of the GNU Affero General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20use std::error::Error as StdError;
21use std::{fmt, io};
22
23use rusoto_core::RusotoError;
24#[cfg(feature = "kinesis")]
25use rusoto_kinesis::{
26    CreateStreamError, DeleteStreamError, DescribeStreamError, GetRecordsError,
27    GetShardIteratorError, ListShardsError, ListStreamsError, MergeShardsError, SplitShardError,
28};
29use rusoto_s3::{
30    AbortMultipartUploadError, CompleteMultipartUploadError, CreateMultipartUploadError,
31    DeleteObjectError, GetObjectError, HeadObjectError, PutObjectError, UploadPartError,
32};
33
34use crate::retry::Retryable;
35
36pub struct RusotoErrorWrapper<T: Retryable + StdError>(pub RusotoError<T>);
37
38impl<T: Retryable + StdError> From<RusotoError<T>> for RusotoErrorWrapper<T> {
39    fn from(err: RusotoError<T>) -> Self {
40        RusotoErrorWrapper(err)
41    }
42}
43
44impl<T: Retryable + StdError + 'static> StdError for RusotoErrorWrapper<T> {
45    fn source(&self) -> Option<&(dyn StdError + 'static)> {
46        Some(&self.0)
47    }
48}
49
50impl<T: Retryable + StdError> fmt::Debug for RusotoErrorWrapper<T> {
51    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52        write!(f, "{:?}", self.0)
53    }
54}
55
56impl<T: Retryable + StdError + 'static> fmt::Display for RusotoErrorWrapper<T> {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", self.0)
59    }
60}
61
62impl<T: Retryable + StdError> From<io::Error> for RusotoErrorWrapper<T> {
63    fn from(err: io::Error) -> Self {
64        RusotoErrorWrapper::from(RusotoError::from(err))
65    }
66}
67
68impl<T: Retryable + StdError> Retryable for RusotoErrorWrapper<T> {
69    fn is_retryable(&self) -> bool {
70        match &self.0 {
71            RusotoError::HttpDispatch(_) => true,
72            RusotoError::Service(service_error) => service_error.is_retryable(),
73            RusotoError::Unknown(http_resp) => http_resp.status.is_server_error(),
74            _ => false,
75        }
76    }
77}
78
79impl Retryable for GetObjectError {
80    fn is_retryable(&self) -> bool {
81        false
82    }
83}
84
85impl Retryable for DeleteObjectError {
86    fn is_retryable(&self) -> bool {
87        false
88    }
89}
90
91impl Retryable for UploadPartError {
92    fn is_retryable(&self) -> bool {
93        false
94    }
95}
96
97impl Retryable for CompleteMultipartUploadError {
98    fn is_retryable(&self) -> bool {
99        false
100    }
101}
102
103impl Retryable for AbortMultipartUploadError {
104    fn is_retryable(&self) -> bool {
105        false
106    }
107}
108
109impl Retryable for CreateMultipartUploadError {
110    fn is_retryable(&self) -> bool {
111        false
112    }
113}
114
115impl Retryable for PutObjectError {
116    fn is_retryable(&self) -> bool {
117        false
118    }
119}
120
121impl Retryable for HeadObjectError {
122    fn is_retryable(&self) -> bool {
123        false
124    }
125}
126
127#[cfg(feature = "kinesis")]
128impl Retryable for GetRecordsError {
129    fn is_retryable(&self) -> bool {
130        match self {
131            GetRecordsError::KMSThrottling(_) => true,
132            GetRecordsError::ProvisionedThroughputExceeded(_) => true,
133            _ => false,
134        }
135    }
136}
137
138#[cfg(feature = "kinesis")]
139impl Retryable for GetShardIteratorError {
140    fn is_retryable(&self) -> bool {
141        matches!(
142            self,
143            GetShardIteratorError::ProvisionedThroughputExceeded(_)
144        )
145    }
146}
147
148#[cfg(feature = "kinesis")]
149impl Retryable for ListShardsError {
150    fn is_retryable(&self) -> bool {
151        false
152    }
153}
154
155#[cfg(feature = "kinesis")]
156impl Retryable for CreateStreamError {
157    fn is_retryable(&self) -> bool {
158        false
159    }
160}
161
162#[cfg(feature = "kinesis")]
163impl Retryable for DeleteStreamError {
164    fn is_retryable(&self) -> bool {
165        false
166    }
167}
168
169#[cfg(feature = "kinesis")]
170impl Retryable for DescribeStreamError {
171    fn is_retryable(&self) -> bool {
172        false
173    }
174}
175
176#[cfg(feature = "kinesis")]
177impl Retryable for ListStreamsError {
178    fn is_retryable(&self) -> bool {
179        false
180    }
181}
182
183#[cfg(feature = "kinesis")]
184impl Retryable for MergeShardsError {
185    fn is_retryable(&self) -> bool {
186        false
187    }
188}
189
190#[cfg(feature = "kinesis")]
191impl Retryable for SplitShardError {
192    fn is_retryable(&self) -> bool {
193        false
194    }
195}