This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Scraper service — a Rust/Axum backend for web scraping (anime/komik data extraction) and image proxy/CDN caching. Serves as the backend engine consumed by the `apps/solidjs` frontend.
## Commands
```bash
# Development
cargo run # Start server (binds 0.0.0.0:4091)
cargo test# Run all tests
cargo clippy -- -D warnings # Lint (warnings are errors)
cargo fmt # Auto-format all source files
# Release build (full LTO, single CGU, stripped)
cargo build --release
# PM2 production
pm2 start ecosystem.config.cjs --env production # Uses target/release/scraper
```
## Architecture
### Modular MVC + Service + Repository
Setiap module mengikuti arsitektur layered yang identik:
5.**Lazy batch helper**: `cache_image_urls_batch_lazy()` — Redis batch check → DB batch check → background spawn untuk misses
### HasPoster Trait & apply_cached_posters
`HasPoster` trait di `shared/types/entities/anime.rs` memungkinkan generic poster caching:
```rust
pubtraitHasPoster{
fnposter(&self)-> &str;
fnset_poster(&mutself,url: String);
}
```
Semua item type dengan field `poster` mengimplementasikan trait ini (`OngoingAnimeItem`, `KomikItem`, `FilterAnimeItem`, `Recommendation`, dll).
`apply_cached_posters()` di `shared/services/images/cache.rs` menerima `&mut [T]` where `T: HasPoster`, menggantikan pola manual ~15 baris yang sebelumnya berulang di setiap service method.
Semua module repository (`AnimeRepository`, `Anime2Repository`, `KomikRepository`, `ProxyRepository`) mengimplementasikan trait ini.
### Error Handling
`AppError` enum di `src/shared/errors/app_error.rs` — derives `thiserror::Error` dan implements `IntoResponse` (404 untuk `NotFound`, 500 untuk lainnya).
- **Minimal dependencies**: Before adding a crate, evaluate if existing deps or std can handle it.
- **Dead code**: Remove unused functions, types, modules rather than leaving them.
- **Performance**: Use `spawn_blocking` for CPU-heavy work (HTML parsing).
- **No duplicate infrastructure**: Satu trait, satu impl. Jangan membuat trait/repository duplikat seperti `ImageRepository` dan `ImageCacheRepository` yang berbeda.
- **No thin wrappers**: Hindari wrapper tipis seperti `CacheImageUseCase` yang hanya meneruskan panggilan ke service lain.
## Useful Endpoints
-`GET /docs` — Swagger UI
-`GET /api-docs/openapi.json` — OpenAPI spec
-`POST /api/proxy/image-cache` — Cache an image URL