mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-19 19:44:40 +00:00
Use exponential backoff for publish retries (#9276)
## Summary Just trying to unify the retry handling, as in https://github.com/astral-sh/uv/pull/9274 and elsewhere. Right now, the publish handler doesn't use any backoff and always retries three times regardless of settings.
This commit is contained in:
parent
110c38e549
commit
8ca8de8eaa
2 changed files with 18 additions and 13 deletions
|
|
@ -11,11 +11,12 @@ use reqwest::header::AUTHORIZATION;
|
||||||
use reqwest::multipart::Part;
|
use reqwest::multipart::Part;
|
||||||
use reqwest::{Body, Response, StatusCode};
|
use reqwest::{Body, Response, StatusCode};
|
||||||
use reqwest_middleware::RequestBuilder;
|
use reqwest_middleware::RequestBuilder;
|
||||||
use reqwest_retry::{Retryable, RetryableStrategy};
|
use reqwest_retry::{RetryPolicy, Retryable, RetryableStrategy};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
use std::{env, fmt, io};
|
use std::{env, fmt, io};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::io::{AsyncReadExt, BufReader};
|
use tokio::io::{AsyncReadExt, BufReader};
|
||||||
|
|
@ -365,7 +366,6 @@ pub async fn upload(
|
||||||
filename: &DistFilename,
|
filename: &DistFilename,
|
||||||
registry: &Url,
|
registry: &Url,
|
||||||
client: &BaseClient,
|
client: &BaseClient,
|
||||||
retries: u32,
|
|
||||||
username: Option<&str>,
|
username: Option<&str>,
|
||||||
password: Option<&str>,
|
password: Option<&str>,
|
||||||
check_url_client: Option<&CheckUrlClient<'_>>,
|
check_url_client: Option<&CheckUrlClient<'_>>,
|
||||||
|
|
@ -375,8 +375,9 @@ pub async fn upload(
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PublishError::PublishPrepare(file.to_path_buf(), Box::new(err)))?;
|
.map_err(|err| PublishError::PublishPrepare(file.to_path_buf(), Box::new(err)))?;
|
||||||
|
|
||||||
// Retry loop
|
let mut n_past_retries = 0;
|
||||||
let mut attempt = 0;
|
let start_time = SystemTime::now();
|
||||||
|
let retry_policy = client.retry_policy();
|
||||||
loop {
|
loop {
|
||||||
let (request, idx) = build_request(
|
let (request, idx) = build_request(
|
||||||
file,
|
file,
|
||||||
|
|
@ -393,11 +394,18 @@ pub async fn upload(
|
||||||
.map_err(|err| PublishError::PublishPrepare(file.to_path_buf(), Box::new(err)))?;
|
.map_err(|err| PublishError::PublishPrepare(file.to_path_buf(), Box::new(err)))?;
|
||||||
|
|
||||||
let result = request.send().await;
|
let result = request.send().await;
|
||||||
if attempt < retries && UvRetryableStrategy.handle(&result) == Some(Retryable::Transient) {
|
if UvRetryableStrategy.handle(&result) == Some(Retryable::Transient) {
|
||||||
reporter.on_download_complete(idx);
|
let retry_decision = retry_policy.should_retry(start_time, n_past_retries);
|
||||||
warn_user!("Transient request failure for {}, retrying", registry);
|
if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision {
|
||||||
attempt += 1;
|
warn_user!("Transient failure while handling response for {registry}; retrying...",);
|
||||||
continue;
|
reporter.on_download_complete(idx);
|
||||||
|
let duration = execute_after
|
||||||
|
.duration_since(SystemTime::now())
|
||||||
|
.unwrap_or_else(|_| Duration::default());
|
||||||
|
tokio::time::sleep(duration).await;
|
||||||
|
n_past_retries += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = result.map_err(|err| {
|
let response = result.map_err(|err| {
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,7 @@ use std::time::Duration;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_client::{
|
use uv_client::{AuthIntegration, BaseClientBuilder, Connectivity, RegistryClientBuilder};
|
||||||
AuthIntegration, BaseClientBuilder, Connectivity, RegistryClientBuilder, DEFAULT_RETRIES,
|
|
||||||
};
|
|
||||||
use uv_configuration::{KeyringProviderType, TrustedHost, TrustedPublishing};
|
use uv_configuration::{KeyringProviderType, TrustedHost, TrustedPublishing};
|
||||||
use uv_distribution_types::{Index, IndexCapabilities, IndexLocations, IndexUrl};
|
use uv_distribution_types::{Index, IndexCapabilities, IndexLocations, IndexUrl};
|
||||||
use uv_publish::{
|
use uv_publish::{
|
||||||
|
|
@ -176,7 +174,6 @@ pub(crate) async fn publish(
|
||||||
&filename,
|
&filename,
|
||||||
&publish_url,
|
&publish_url,
|
||||||
&upload_client,
|
&upload_client,
|
||||||
DEFAULT_RETRIES,
|
|
||||||
username.as_deref(),
|
username.as_deref(),
|
||||||
password.as_deref(),
|
password.as_deref(),
|
||||||
check_url_client.as_ref(),
|
check_url_client.as_ref(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue