feat: full clean architecture refactor — domain → application → infrastructure → presentation

- Restructure from Modular MVC to Clean Architecture with 4 strict layers
- Domain: entities (anime/komik/proxy), Repository traits, typed errors
- Application: use case classes with proper error propagation
- Infrastructure: repository impls, parsers, Redis cache, HTTP/scraping, browser
- Presentation: Axum handlers, DTOs, AppState, router, AppError+IntoResponse
- Migrate all parsers (otakudesu, alqanime, komik) to native infra implementations
- Replace once_cell::sync::Lazy/OnceCell with std::sync::LazyLock/OnceLock
- Remove 150+ old files in modules/ and shared/ directories
- Remove once_cell from Cargo.toml dependencies
- Fix test/debug binaries to use new import paths
- Zero new clippy warnings

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
asepharyana
2026-07-21 12:54:23 +07:00
co-authored by Claude Opus 4.8
parent 80c96eaa42
commit 776fa828d8
205 changed files with 4241 additions and 14569 deletions
+66
View File
@@ -0,0 +1,66 @@
//! HTTP retry utilities with exponential backoff.
use backoff::ExponentialBackoff;
use std::time::Duration;
/// Default retry configuration for HTTP requests.
pub fn default_backoff() -> ExponentialBackoff {
ExponentialBackoff {
initial_interval: Duration::from_millis(500),
max_interval: Duration::from_secs(10),
multiplier: 2.0,
max_elapsed_time: Some(Duration::from_secs(30)),
..Default::default()
}
}
/// Create a custom exponential backoff.
pub fn custom_backoff(
initial_ms: u64,
max_secs: u64,
multiplier: f64,
max_elapsed_secs: u64,
) -> ExponentialBackoff {
ExponentialBackoff {
initial_interval: Duration::from_millis(initial_ms),
max_interval: Duration::from_secs(max_secs),
multiplier,
max_elapsed_time: Some(Duration::from_secs(max_elapsed_secs)),
..Default::default()
}
}
/// Quick backoff for fast retries (3 attempts, 100ms initial).
pub fn quick_backoff() -> ExponentialBackoff {
ExponentialBackoff {
initial_interval: Duration::from_millis(100),
max_interval: Duration::from_secs(1),
multiplier: 2.0,
max_elapsed_time: Some(Duration::from_secs(5)),
..Default::default()
}
}
/// Slow backoff for long operations (10 attempts, 1s initial).
pub fn slow_backoff() -> ExponentialBackoff {
ExponentialBackoff {
initial_interval: Duration::from_secs(1),
max_interval: Duration::from_secs(30),
multiplier: 2.0,
max_elapsed_time: Some(Duration::from_secs(120)),
..Default::default()
}
}
/// Make an error transient (will be retried).
pub fn transient<E>(err: E) -> backoff::Error<E> {
backoff::Error::transient(err)
}
/// Make an error permanent (will NOT be retried).
pub fn permanent<E>(err: E) -> backoff::Error<E> {
backoff::Error::permanent(err)
}
// Re-export retry function for convenience
pub use backoff::future::retry;