Use a higher timeout for publishing (#7923)

This commit is contained in:
konsti 2024-10-04 15:52:23 +02:00 committed by GitHub
parent d73b25385f
commit ad638d7fa3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 34 additions and 22 deletions

View File

@ -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
} }

View File

@ -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 {

View File

@ -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 {

View File

@ -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)