use std::num::NonZero;
use std::thread::available_parallelism;
use std::time::Duration;
use secrecy::SecretString;
use serde::Deserialize;
use tokio_retry2::strategy::ExponentialFactorBackoff;
use tokio_retry2::strategy::MaxInterval;
const DEFAULT_RETRIES: usize = 5;
#[derive(Debug, Clone, Deserialize)]
pub struct S3AuthConfig {
pub access_key_id: String,
pub secret_access_key: SecretString,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GoogleAuthConfig {
pub access_key: String,
pub secret: SecretString,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct AzureConfig {
#[serde(default)]
pub use_azurite: bool,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct S3Config {
#[serde(default)]
pub region: Option<String>,
#[serde(default)]
pub auth: Option<S3AuthConfig>,
#[serde(default)]
pub use_localstack: bool,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct GoogleConfig {
#[serde(default)]
pub auth: Option<GoogleAuthConfig>,
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct Config {
#[serde(default)]
pub link_to_cache: bool,
#[serde(default)]
pub overwrite: bool,
#[serde(default)]
pub block_size: Option<u64>,
#[serde(default)]
pub parallelism: Option<usize>,
#[serde(default)]
pub retries: Option<usize>,
#[serde(default)]
pub azure: AzureConfig,
#[serde(default)]
pub s3: S3Config,
#[serde(default)]
pub google: GoogleConfig,
}
impl Config {
pub fn parallelism(&self) -> usize {
self.parallelism
.unwrap_or_else(|| available_parallelism().map(NonZero::get).unwrap_or(1))
}
pub fn retry_durations<'a>(&self) -> impl Iterator<Item = Duration> + use<'a> {
const INITIAL_DELAY_MILLIS: u64 = 1000;
const BASE_FACTOR: f64 = 2.0;
const MAX_DURATION: Duration = Duration::from_secs(600);
ExponentialFactorBackoff::from_millis(INITIAL_DELAY_MILLIS, BASE_FACTOR)
.max_duration(MAX_DURATION)
.take(self.retries.unwrap_or(DEFAULT_RETRIES))
}
}