use std::time::Duration;
pub(super) const INITIAL_BACKOFF_SECS: u64 = 5;
pub(super) const MAX_BACKOFF_SECS: u64 = 60;
pub(super) const MIN_RETRY_BUDGET_SECS: u64 = 60;
pub(super) const MAX_RETRY_BUDGET_SECS: u64 = 300;
pub(super) fn retry_budget(profile_timeout_secs: u64) -> Duration {
Duration::from_secs(profile_timeout_secs.clamp(MIN_RETRY_BUDGET_SECS, MAX_RETRY_BUDGET_SECS))
}
pub(super) fn backoff_for(attempt: u32) -> Duration {
backoff_for_with(attempt, INITIAL_BACKOFF_SECS, MAX_BACKOFF_SECS)
}
#[cfg(test)]
pub(super) fn backoff_for_test(attempt: u32, initial: Duration, cap: Duration) -> Duration {
backoff_for_with_millis(
attempt,
initial.as_millis().max(1) as u64,
cap.as_millis().max(1) as u64,
)
}
fn backoff_for_with(attempt: u32, initial_secs: u64, max_secs: u64) -> Duration {
backoff_for_with_millis(
attempt,
initial_secs.saturating_mul(1000),
max_secs.saturating_mul(1000),
)
}
fn backoff_for_with_millis(attempt: u32, initial_ms: u64, max_ms: u64) -> Duration {
const SATURATION_SHIFT: u32 = 20; let shift = attempt.min(SATURATION_SHIFT);
let multiplier = 1_u64.checked_shl(shift).unwrap_or(u64::MAX);
let raw = initial_ms.saturating_mul(multiplier);
Duration::from_millis(raw.min(max_ms))
}