Repository: astral-sh/uv
File: crates/uv-client/src/base_client.rs (Rust)

Code before:
    pub fn new(retry_policy: ExponentialBackoff, url: impl Into<DisplaySafeUrl>) -> Self {
        Self {
            retry_policy,
            start_time: SystemTime::now(),
            total_retries: 0,
            url: url.into(),
        }
    }

    /// The number of retries across all requests.
    ///
    /// After a failed retryable request, this equals the maximum number of retries.
    pub fn total_retries(&self) -> u32 {
        self.total_retries
    }

    /// Whether request should be retried. Waits with backoff if required.
    ///
    /// Takes the number of retries from nested layers associated with the specific `err` type as
    /// `error_retries`.
    pub async fn should_retry(&mut self, err: &(dyn Error + 'static), error_retries: u32) -> bool {
        // Check if the middleware already performed retries
        self.total_retries += error_retries;
        match retryable_on_request_failure(err) {
            Some(Retryable::Transient) => {
                // If middleware already retried, consider that in our retry budget
                let retry_decision = self
                    .retry_policy
                    .should_retry(self.start_time, self.total_retries);
                if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision {
                    let duration = execute_after
                        .duration_since(SystemTime::now())
                        .unwrap_or_else(|_| Duration::default());

                    debug!(
                        "Transient failure while handling response from {}; retrying after {:.1}s...",
                        self.url,
                        duration.as_secs_f32(),
                    );
                    // TODO(konsti): Should we show a spinner plus a message in the CLI while
                    // waiting?
                    tokio::time::sleep(duration).await;
                    self.total_retries += 1;
                    return true;
                }

                false
            }
            Some(Retryable::Fatal) | None => false,
        }
    }

Review comment (suggestion):
I still think this comment is confusing as the point at which we are "considering" the upstream retries is when we add them. I would just drop it.

```suggestion
```

Code after:
    url: DisplaySafeUrl,
}

impl RetryState {
    /// Initialize the [`RetryState`] and start the backoff timer.
    pub fn start(retry_policy: ExponentialBackoff, url: impl Into<DisplaySafeUrl>) -> Self {
        Self {
            retry_policy,
            start_time: SystemTime::now(),
            total_retries: 0,
            url: url.into(),
        }
    }

    /// The number of retries across all requests.
    ///
    /// After a failed retryable request, this equals the maximum number of retries.
    pub fn total_retries(&self) -> u32 {
        self.total_retries
    }

    /// Determines whether request should be retried.
    ///
    /// Takes the number of retries from nested layers associated with the specific `err` type as
    /// `error_retries`.
    ///
    /// Returns the backoff duration if the request should be retried.
    #[must_use]
    pub fn should_retry(
        &mut self,
        err: &(dyn Error + 'static),
        error_retries: u32,
    ) -> Option<Duration> {
        // If the middleware performed any retries, consider them in our budget.
        self.total_retries += error_retries;
        match retryable_on_request_failure(err) {
            Some(Retryable::Transient) => {
                let retry_decision = self
                    .retry_policy
                    .should_retry(self.start_time, self.total_retries);
                if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision {
                    let duration = execute_after
                        .duration_since(SystemTime::now())
                        .unwrap_or_else(|_| Duration::default());

                    self.total_retries += 1;
                    return Some(duration);
                }

                None
            }