Skip to content

Commit 64b87e6

Browse files
fix(api): Merge retryable curl errors into RetryError
1 parent 63df8e7 commit 64b87e6

2 files changed

Lines changed: 31 additions & 56 deletions

File tree

src/api/errors/mod.rs

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,12 @@ pub(super) struct ProjectRenamedError(pub(super) String);
1414
pub(super) type ApiResult<T> = Result<T, ApiError>;
1515

1616
#[derive(Debug, thiserror::Error)]
17-
#[error("request failed with retryable status code {}", .body.status)]
18-
pub(super) struct RetryError {
19-
body: ApiResponse,
20-
}
21-
22-
impl RetryError {
23-
pub fn new(body: ApiResponse) -> Self {
24-
Self { body }
25-
}
26-
27-
pub fn into_body(self) -> ApiResponse {
28-
self.body
29-
}
30-
}
31-
32-
#[derive(Debug, thiserror::Error)]
33-
#[error("request failed with retryable curl error: {source}")]
34-
pub(super) struct RetryableCurlError {
35-
#[source]
36-
source: curl::Error,
37-
}
38-
39-
impl RetryableCurlError {
40-
pub fn new(source: curl::Error) -> Self {
41-
Self { source }
42-
}
43-
44-
pub fn into_source(self) -> curl::Error {
45-
self.source
46-
}
17+
pub(super) enum RetryError {
18+
#[error("request failed with retryable status code {}", body.status)]
19+
Status { body: ApiResponse },
20+
#[error("request failed with retryable error: {source}")]
21+
ApiError {
22+
#[from]
23+
source: ApiError,
24+
},
4725
}

src/api/mod.rs

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use symbolic::common::DebugId;
4242
use symbolic::debuginfo::ObjectKind;
4343
use uuid::Uuid;
4444

45-
use crate::api::errors::{ProjectRenamedError, RetryError, RetryableCurlError};
45+
use crate::api::errors::{ProjectRenamedError, RetryError};
4646
use crate::config::{Auth, Config};
4747
use crate::constants::{ARCH, EXT, PLATFORM, RELEASE_REGISTRY_LATEST_URL, VERSION};
4848
use crate::utils::http::{self, is_absolute_url};
@@ -1314,24 +1314,27 @@ impl ApiRequest {
13141314
debug!("retry number {retry_number}, max retries: {max_retries}");
13151315
*retry_number += 1;
13161316

1317-
let result = self.send_into(&mut out);
1318-
1319-
// Check for retriable curl errors (DNS resolution failure)
1320-
if let Some(curl_err) = result
1321-
.as_ref()
1322-
.err()
1323-
.and_then(|e| e.source())
1324-
.and_then(|s| s.downcast_ref::<curl::Error>())
1325-
.filter(|e| e.is_couldnt_resolve_host())
1326-
{
1327-
anyhow::bail!(RetryableCurlError::new(curl_err.clone()));
1328-
}
1317+
let mut rv = match self.send_into(&mut out) {
1318+
Ok(rv) => rv,
1319+
Err(err) => {
1320+
let is_retryable_dns = err
1321+
.source()
1322+
.and_then(|s| s.downcast_ref::<curl::Error>())
1323+
.is_some_and(|e| e.is_couldnt_resolve_host());
1324+
1325+
// Wrap DNS errors in a RetryError so they get retried
1326+
if is_retryable_dns {
1327+
anyhow::bail!(RetryError::from(err));
1328+
}
1329+
1330+
anyhow::bail!(err);
1331+
}
1332+
};
13291333

1330-
let mut rv = result?;
13311334
rv.body = Some(out);
13321335

13331336
if RETRY_STATUS_CODES.contains(&rv.status) {
1334-
anyhow::bail!(RetryError::new(rv));
1337+
anyhow::bail!(RetryError::Status { body: rv });
13351338
}
13361339

13371340
Ok(rv)
@@ -1340,7 +1343,7 @@ impl ApiRequest {
13401343
send_req
13411344
.retry(backoff)
13421345
.sleep(thread::sleep)
1343-
.when(|e| e.is::<RetryError>() || e.is::<RetryableCurlError>())
1346+
.when(|e| e.is::<RetryError>())
13441347
.notify(|e, dur| {
13451348
debug!(
13461349
"retry number {} failed due to {e:#}, retrying again in {} ms",
@@ -1349,16 +1352,10 @@ impl ApiRequest {
13491352
);
13501353
})
13511354
.call()
1352-
.or_else(|err| {
1353-
err.downcast::<RetryError>()
1354-
.map(RetryError::into_body)
1355-
.map_err(|err| {
1356-
err.downcast::<RetryableCurlError>()
1357-
.map(|e| ApiError::from(e.into_source()))
1358-
.unwrap_or_else(|e| {
1359-
ApiError::with_source(ApiErrorKind::RequestFailed, e)
1360-
})
1361-
})
1355+
.or_else(|err| match err.downcast::<RetryError>() {
1356+
Ok(RetryError::Status { body }) => Ok(body),
1357+
Ok(RetryError::ApiError { source }) => Err(source),
1358+
Err(err) => Err(ApiError::with_source(ApiErrorKind::RequestFailed, err)),
13621359
})
13631360
}
13641361
}

0 commit comments

Comments
 (0)