mirror of https://github.com/astral-sh/uv
Use a higher timeout for publishing (#7923)
This commit is contained in:
parent
d73b25385f
commit
ad638d7fa3
|
|
@ -1,8 +1,3 @@
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::{env, iter};
|
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use reqwest::{Client, ClientBuilder, Response};
|
use reqwest::{Client, ClientBuilder, Response};
|
||||||
use reqwest_middleware::ClientWithMiddleware;
|
use reqwest_middleware::ClientWithMiddleware;
|
||||||
|
|
@ -10,6 +5,11 @@ use reqwest_retry::policies::ExponentialBackoff;
|
||||||
use reqwest_retry::{
|
use reqwest_retry::{
|
||||||
DefaultRetryableStrategy, RetryTransientMiddleware, Retryable, RetryableStrategy,
|
DefaultRetryableStrategy, RetryTransientMiddleware, Retryable, RetryableStrategy,
|
||||||
};
|
};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::{env, iter};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uv_auth::AuthMiddleware;
|
use uv_auth::AuthMiddleware;
|
||||||
|
|
@ -52,6 +52,7 @@ pub struct BaseClientBuilder<'a> {
|
||||||
markers: Option<&'a MarkerEnvironment>,
|
markers: Option<&'a MarkerEnvironment>,
|
||||||
platform: Option<&'a Platform>,
|
platform: Option<&'a Platform>,
|
||||||
auth_integration: AuthIntegration,
|
auth_integration: AuthIntegration,
|
||||||
|
default_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BaseClientBuilder<'_> {
|
impl Default for BaseClientBuilder<'_> {
|
||||||
|
|
@ -72,6 +73,7 @@ impl BaseClientBuilder<'_> {
|
||||||
markers: None,
|
markers: None,
|
||||||
platform: None,
|
platform: None,
|
||||||
auth_integration: AuthIntegration::default(),
|
auth_integration: AuthIntegration::default(),
|
||||||
|
default_timeout: Duration::from_secs(30),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +133,12 @@ impl<'a> BaseClientBuilder<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn default_timeout(mut self, default_timeout: Duration) -> Self {
|
||||||
|
self.default_timeout = default_timeout;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_offline(&self) -> bool {
|
pub fn is_offline(&self) -> bool {
|
||||||
matches!(self.connectivity, Connectivity::Offline)
|
matches!(self.connectivity, Connectivity::Offline)
|
||||||
}
|
}
|
||||||
|
|
@ -161,20 +169,20 @@ impl<'a> BaseClientBuilder<'a> {
|
||||||
|
|
||||||
// Timeout options, matching https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout
|
// Timeout options, matching https://doc.rust-lang.org/nightly/cargo/reference/config.html#httptimeout
|
||||||
// `UV_REQUEST_TIMEOUT` is provided for backwards compatibility with v0.1.6
|
// `UV_REQUEST_TIMEOUT` is provided for backwards compatibility with v0.1.6
|
||||||
let default_timeout = 30;
|
|
||||||
let timeout = env::var("UV_HTTP_TIMEOUT")
|
let timeout = env::var("UV_HTTP_TIMEOUT")
|
||||||
.or_else(|_| env::var("UV_REQUEST_TIMEOUT"))
|
.or_else(|_| env::var("UV_REQUEST_TIMEOUT"))
|
||||||
.or_else(|_| env::var("HTTP_TIMEOUT"))
|
.or_else(|_| env::var("HTTP_TIMEOUT"))
|
||||||
.and_then(|value| {
|
.and_then(|value| {
|
||||||
value.parse::<u64>()
|
value.parse::<u64>()
|
||||||
|
.map(Duration::from_secs)
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
// On parse error, warn and use the default timeout
|
// On parse error, warn and use the default timeout
|
||||||
warn_user_once!("Ignoring invalid value from environment for `UV_HTTP_TIMEOUT`. Expected an integer number of seconds, got \"{value}\".");
|
warn_user_once!("Ignoring invalid value from environment for `UV_HTTP_TIMEOUT`. Expected an integer number of seconds, got \"{value}\".");
|
||||||
Ok(default_timeout)
|
Ok(self.default_timeout)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap_or(default_timeout);
|
.unwrap_or(self.default_timeout);
|
||||||
debug!("Using request timeout of {timeout}s");
|
debug!("Using request timeout of {}s", timeout.as_secs());
|
||||||
|
|
||||||
// Create a secure client that validates certificates.
|
// Create a secure client that validates certificates.
|
||||||
let raw_client = self.create_client(
|
let raw_client = self.create_client(
|
||||||
|
|
@ -227,7 +235,7 @@ impl<'a> BaseClientBuilder<'a> {
|
||||||
fn create_client(
|
fn create_client(
|
||||||
&self,
|
&self,
|
||||||
user_agent: &str,
|
user_agent: &str,
|
||||||
timeout: u64,
|
timeout: Duration,
|
||||||
ssl_cert_file_exists: bool,
|
ssl_cert_file_exists: bool,
|
||||||
security: Security,
|
security: Security,
|
||||||
) -> Client {
|
) -> Client {
|
||||||
|
|
@ -236,7 +244,7 @@ impl<'a> BaseClientBuilder<'a> {
|
||||||
.http1_title_case_headers()
|
.http1_title_case_headers()
|
||||||
.user_agent(user_agent)
|
.user_agent(user_agent)
|
||||||
.pool_max_idle_per_host(20)
|
.pool_max_idle_per_host(20)
|
||||||
.read_timeout(std::time::Duration::from_secs(timeout))
|
.read_timeout(timeout)
|
||||||
.tls_built_in_root_certs(false);
|
.tls_built_in_root_certs(false);
|
||||||
|
|
||||||
// If necessary, accept invalid certificates.
|
// If necessary, accept invalid certificates.
|
||||||
|
|
@ -327,7 +335,7 @@ pub struct BaseClient {
|
||||||
/// The connectivity mode to use.
|
/// The connectivity mode to use.
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
/// Configured client timeout, in seconds.
|
/// Configured client timeout, in seconds.
|
||||||
timeout: u64,
|
timeout: Duration,
|
||||||
/// Hosts that are trusted to use the insecure client.
|
/// Hosts that are trusted to use the insecure client.
|
||||||
allow_insecure_host: Vec<TrustedHost>,
|
allow_insecure_host: Vec<TrustedHost>,
|
||||||
}
|
}
|
||||||
|
|
@ -365,7 +373,7 @@ impl BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The configured client timeout, in seconds.
|
/// The configured client timeout, in seconds.
|
||||||
pub fn timeout(&self) -> u64 {
|
pub fn timeout(&self) -> Duration {
|
||||||
self.timeout
|
self.timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use async_http_range_reader::AsyncHttpRangeReader;
|
use async_http_range_reader::AsyncHttpRangeReader;
|
||||||
use futures::{FutureExt, TryStreamExt};
|
use futures::{FutureExt, TryStreamExt};
|
||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use reqwest::{Client, Response, StatusCode};
|
use reqwest::{Client, Response, StatusCode};
|
||||||
use reqwest_middleware::ClientWithMiddleware;
|
use reqwest_middleware::ClientWithMiddleware;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::time::Duration;
|
||||||
use tracing::{info_span, instrument, trace, warn, Instrument};
|
use tracing::{info_span, instrument, trace, warn, Instrument};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
|
@ -171,7 +171,7 @@ pub struct RegistryClient {
|
||||||
/// The connectivity mode to use.
|
/// The connectivity mode to use.
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
/// Configured client timeout, in seconds.
|
/// Configured client timeout, in seconds.
|
||||||
timeout: u64,
|
timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegistryClient {
|
impl RegistryClient {
|
||||||
|
|
@ -191,7 +191,7 @@ impl RegistryClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the timeout this client is configured with, in seconds.
|
/// Return the timeout this client is configured with, in seconds.
|
||||||
pub fn timeout(&self) -> u64 {
|
pub fn timeout(&self) -> Duration {
|
||||||
self.timeout
|
self.timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -713,7 +713,7 @@ impl RegistryClient {
|
||||||
std::io::Error::new(
|
std::io::Error::new(
|
||||||
std::io::ErrorKind::TimedOut,
|
std::io::ErrorKind::TimedOut,
|
||||||
format!(
|
format!(
|
||||||
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).", self.timeout()
|
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).", self.timeout().as_secs()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::TimedOut,
|
io::ErrorKind::TimedOut,
|
||||||
format!(
|
format!(
|
||||||
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).", self.client.unmanaged.timeout()
|
"Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: {}s).", self.client.unmanaged.timeout().as_secs()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use anyhow::{bail, Result};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uv_client::{AuthIntegration, BaseClientBuilder, Connectivity, DEFAULT_RETRIES};
|
use uv_client::{AuthIntegration, BaseClientBuilder, Connectivity, DEFAULT_RETRIES};
|
||||||
|
|
@ -50,6 +51,9 @@ pub(crate) async fn publish(
|
||||||
.allow_insecure_host(allow_insecure_host)
|
.allow_insecure_host(allow_insecure_host)
|
||||||
// Don't try cloning the request to make an unauthenticated request first.
|
// Don't try cloning the request to make an unauthenticated request first.
|
||||||
.auth_integration(AuthIntegration::OnlyAuthenticated)
|
.auth_integration(AuthIntegration::OnlyAuthenticated)
|
||||||
|
// Set a very high timeout for uploads, connections are often 10x slower on upload than
|
||||||
|
// download. 15 min is taken from the time a trusted publishing token is valid.
|
||||||
|
.default_timeout(Duration::from_secs(15 * 60))
|
||||||
.build();
|
.build();
|
||||||
let oidc_client = BaseClientBuilder::new()
|
let oidc_client = BaseClientBuilder::new()
|
||||||
.auth_integration(AuthIntegration::NoAuthMiddleware)
|
.auth_integration(AuthIntegration::NoAuthMiddleware)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue