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
+47
View File
@@ -0,0 +1,47 @@
//! Database schema initialization.
use sea_orm::{ConnectionTrait, DatabaseConnection, Schema, Statement};
use tracing::info;
use crate::infrastructure::persistence::entities::image_cache;
pub async fn init(db: &DatabaseConnection) -> Result<(), sea_orm::DbErr> {
info!("🚀 Initializing database schema...");
let backend = db.get_database_backend();
let schema = Schema::new(backend);
let tables = vec![(
"ImageCache",
schema
.create_table_from_entity(image_cache::Entity)
.if_not_exists()
.to_owned(),
)];
for (name, stmt) in tables {
match db.execute(backend.build(&stmt)).await {
Ok(_) => info!(" ✓ Table '{}' checked/created", name),
Err(e) => {
tracing::error!(" [!] Failed to create table '{}': {}", name, e);
return Err(e);
}
}
}
let index_sql =
"CREATE INDEX IF NOT EXISTS idx_image_cache_cdn_url ON \"ImageCache\" (cdn_url)";
match db.execute(Statement::from_string(backend, index_sql)).await {
Ok(_) => info!(" ✓ Index 'idx_image_cache_cdn_url' ensured"),
Err(e) => {
let err_str = e.to_string();
if err_str.contains("already exists") || err_str.contains("duplicate") {
info!(" ✓ Index 'idx_image_cache_cdn_url' already exists");
} else {
tracing::error!(" [!] Failed to create index on ImageCache: {}", e);
}
}
}
info!("✅ Database schema initialization complete.");
Ok(())
}