Add trace logs to is_extended_transient_error (#9248)
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
@@ -11,7 +11,7 @@ use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::{env, iter};
|
||||
use tracing::debug;
|
||||
use tracing::{debug, trace};
|
||||
use url::Url;
|
||||
use uv_auth::AuthMiddleware;
|
||||
use uv_configuration::{KeyringProviderType, TrustedHost};
|
||||
@@ -461,39 +461,53 @@ impl RetryableStrategy for UvRetryableStrategy {
|
||||
///
|
||||
/// These cases should be safe to retry with [`Retryable::Transient`].
|
||||
pub(crate) fn is_extended_transient_error(err: &dyn Error) -> bool {
|
||||
// First, look for `WrappedReqwestError`, which wraps `reqwest::Error` but doesn't always
|
||||
// include it in the source.
|
||||
trace!("Attempting to retry error: {err:?}");
|
||||
|
||||
if let Some(err) = find_source::<WrappedReqwestError>(&err) {
|
||||
// First, look for `WrappedReqwestError`, which wraps `reqwest::Error` but doesn't always
|
||||
// include it in the source.
|
||||
if let Some(io) = find_source::<std::io::Error>(&err) {
|
||||
if io.kind() == std::io::ErrorKind::ConnectionReset
|
||||
|| io.kind() == std::io::ErrorKind::UnexpectedEof
|
||||
{
|
||||
trace!(
|
||||
"Retrying error: `ConnectionReset` or `UnexpectedEof` (`WrappedReqwestError`)"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
trace!("Cannot retry error: not one of `ConnectionReset` or `UnexpectedEof` (`WrappedReqwestError`)");
|
||||
} else {
|
||||
trace!("Cannot retry error: not an IO error (`WrappedReqwestError`)");
|
||||
}
|
||||
}
|
||||
|
||||
// Next, look for `reqwest_middleware::Error`, which wraps `reqwest::Error`, but also includes
|
||||
// errors from the middleware stack.
|
||||
if let Some(err) = find_source::<reqwest_middleware::Error>(&err) {
|
||||
} else if let Some(err) = find_source::<reqwest_middleware::Error>(&err) {
|
||||
// Next, look for `reqwest_middleware::Error`, which wraps `reqwest::Error`, but also
|
||||
// includes errors from the middleware stack.
|
||||
if let Some(io) = find_source::<std::io::Error>(&err) {
|
||||
if io.kind() == std::io::ErrorKind::ConnectionReset
|
||||
|| io.kind() == std::io::ErrorKind::UnexpectedEof
|
||||
{
|
||||
trace!("Retrying error: `ConnectionReset` or `UnexpectedEof` (`reqwest_middleware::Error`)");
|
||||
return true;
|
||||
}
|
||||
trace!("Cannot retry error: not one of `ConnectionReset` or `UnexpectedEof` (`reqwest_middleware::Error`)");
|
||||
} else {
|
||||
trace!("Cannot retry error: not an IO error (`reqwest_middleware::Error`)");
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, look for `reqwest::Error`, which is the most common error type.
|
||||
if let Some(err) = find_source::<reqwest::Error>(&err) {
|
||||
} else if let Some(err) = find_source::<reqwest::Error>(&err) {
|
||||
// Finally, look for `reqwest::Error`, which is the most common error type.
|
||||
if let Some(io) = find_source::<std::io::Error>(&err) {
|
||||
if io.kind() == std::io::ErrorKind::ConnectionReset
|
||||
|| io.kind() == std::io::ErrorKind::UnexpectedEof
|
||||
{
|
||||
trace!("Retrying error: `ConnectionReset` or `UnexpectedEof` (`reqwest::Error`)");
|
||||
return true;
|
||||
}
|
||||
trace!("Cannot retry error: not one of `ConnectionReset` or `UnexpectedEof` (`reqwest::Error`)");
|
||||
} else {
|
||||
trace!("Cannot retry error: not an IO error (`reqwest::Error`)");
|
||||
}
|
||||
} else {
|
||||
trace!("Cannot retry error: not a reqwest error");
|
||||
}
|
||||
|
||||
false
|
||||
|
||||
@@ -621,15 +621,15 @@ impl CachedClient {
|
||||
let result = self
|
||||
.get_cacheable(fresh_req, cache_entry, cache_control, &response_callback)
|
||||
.await;
|
||||
if let Some(err) = result
|
||||
if result
|
||||
.as_ref()
|
||||
.err()
|
||||
.filter(|err| is_extended_transient_error(err))
|
||||
.is_some_and(|err| is_extended_transient_error(err))
|
||||
{
|
||||
let retry_decision = retry_policy.should_retry(start_time, n_past_retries);
|
||||
if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision {
|
||||
debug!(
|
||||
"Transient failure while handling response from {}; retrying: {err}",
|
||||
"Transient failure while handling response from {}; retrying...",
|
||||
req.url(),
|
||||
);
|
||||
let duration = execute_after
|
||||
@@ -670,15 +670,15 @@ impl CachedClient {
|
||||
let result = self
|
||||
.skip_cache(fresh_req, cache_entry, &response_callback)
|
||||
.await;
|
||||
if let Some(err) = result
|
||||
if result
|
||||
.as_ref()
|
||||
.err()
|
||||
.filter(|err| is_extended_transient_error(err))
|
||||
.is_some_and(|err| is_extended_transient_error(err))
|
||||
{
|
||||
let retry_decision = retry_policy.should_retry(start_time, n_past_retries);
|
||||
if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision {
|
||||
debug!(
|
||||
"Transient failure while handling response from {}; retrying: {err}",
|
||||
"Transient failure while handling response from {}; retrying...",
|
||||
req.url(),
|
||||
);
|
||||
let duration = execute_after
|
||||
|
||||
Reference in New Issue
Block a user