feat: improved msg for network timeouts (#1961)

## Summary

Closes #1922

When a timeout occurs, it hints to the user to configure the
`UV_HTTP_TIMEOUT` env var.

Before
```
error: Failed to download distributions
  Caused by: Failed to fetch wheel: torch==2.2.0 
  Caused by: Failed to extract source distribution
  Caused by: request or response body error: operation timed out
  Caused by: operation timed out
```

After
```
error: Failed to download distributions
  Caused by: Failed to fetch wheel: torch==2.2.0 
  Caused by: Failed to extract source distribution
  Caused by: Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT.
```

## Test Plan

<!-- How was it tested? -->
Wasn't sure if we'd want a test. If we do, is there a existing mechanism
or preferred approach to force a timeout to occur in tests? Maybe set
the timeout to 1 and add torch as an install check (although it's
possible that could become flaky)?
This commit is contained in:
samypr100 2024-02-25 16:13:28 -05:00 committed by GitHub
parent 06a7c7fde0
commit 757f8e2f60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 40 additions and 13 deletions

View file

@ -73,6 +73,20 @@ impl<'a, Context: BuildContext + Send + Sync> DistributionDatabase<'a, Context>
}
}
/// Handle a specific `reqwest` error, and convert it to [`io::Error`].
fn handle_response_errors(&self, err: reqwest::Error) -> io::Error {
if err.is_timeout() {
io::Error::new(
io::ErrorKind::TimedOut,
format!(
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).", self.client.timeout()
),
)
} else {
io::Error::new(io::ErrorKind::Other, err)
}
}
/// Either fetch the wheel or fetch and build the source distribution
///
/// If `no_remote_wheel` is set, the wheel will be built from a source distribution
@ -150,7 +164,7 @@ impl<'a, Context: BuildContext + Send + Sync> DistributionDatabase<'a, Context>
async {
let reader = response
.bytes_stream()
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
.map_err(|err| self.handle_response_errors(err))
.into_async_read();
// Download and unzip the wheel to a temporary directory.
@ -212,7 +226,7 @@ impl<'a, Context: BuildContext + Send + Sync> DistributionDatabase<'a, Context>
async {
let reader = response
.bytes_stream()
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
.map_err(|err| self.handle_response_errors(err))
.into_async_read();
// Download and unzip the wheel to a temporary directory.