use std::time::Duration;
use crate::providers::{rate_limit::RateLimit, retry::RetryPolicy};
const DEFAULT_PER_PAGE: u32 = 20;
const DEFAULT_RATE_LIMIT: RateLimit = RateLimit::Limited {
max_requests: 90,
per: Duration::from_secs(60),
};
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct AniListConfig {
pub base_url: String,
pub per_page: u32,
pub rate_limit: RateLimit,
pub retry: RetryPolicy,
pub connect_timeout: Option<Duration>,
pub request_timeout: Option<Duration>,
}
impl Default for AniListConfig {
fn default() -> Self {
Self {
base_url: "https://graphql.anilist.co".to_string(),
per_page: DEFAULT_PER_PAGE,
rate_limit: DEFAULT_RATE_LIMIT,
retry: RetryPolicy::default(),
connect_timeout: None,
request_timeout: None,
}
}
}
impl AniListConfig {
pub fn new() -> Self {
Self::default()
}
pub fn new_with_base_url(base_url: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
..Self::default()
}
}
pub fn with_per_page(mut self, per_page: u32) -> Self {
self.per_page = per_page.clamp(1, 50);
self
}
pub fn with_rate_limit(mut self, limit: RateLimit) -> Self {
self.rate_limit = limit;
self
}
pub fn with_retry(mut self, retry: RetryPolicy) -> Self {
self.retry = retry;
self
}
pub fn with_connect_timeout(mut self, timeout: Duration) -> Self {
self.connect_timeout = Some(timeout);
self
}
pub fn with_request_timeout(mut self, timeout: Duration) -> Self {
self.request_timeout = Some(timeout);
self
}
}
#[cfg(test)]
mod tests {
use super::AniListConfig;
#[test]
fn with_per_page_normal() {
let cfg = AniListConfig::new().with_per_page(25);
assert_eq!(cfg.per_page, 25);
}
#[test]
fn with_per_page_clamp_below_min() {
let cfg = AniListConfig::new().with_per_page(0);
assert_eq!(cfg.per_page, 1);
}
#[test]
fn with_per_page_clamp_above_max() {
let cfg = AniListConfig::new().with_per_page(100);
assert_eq!(cfg.per_page, 50);
}
#[test]
fn with_per_page_boundary_values() {
assert_eq!(AniListConfig::new().with_per_page(1).per_page, 1);
assert_eq!(AniListConfig::new().with_per_page(50).per_page, 50);
}
}