docs: add AGENTS.md per module and unify ports to 70XX
- Add CLAUDE.md at root and AGENTS.md in apps/api, apps/indexer, apps/backoffice, crates/parsers with module-specific guidelines - Unify all service ports to 70XX (no more internal/external split): API 7080, Indexer 7081, Backoffice 7082 - Update docker-compose.yml, Dockerfiles, config.rs defaults, .env.example, backoffice routes, bench.sh, smoke.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
75
apps/indexer/AGENTS.md
Normal file
75
apps/indexer/AGENTS.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# apps/indexer — Service d'indexation
|
||||
|
||||
Service background sur le port **7081**. Voir `AGENTS.md` racine pour les conventions globales.
|
||||
|
||||
## Structure des fichiers
|
||||
|
||||
| Fichier | Rôle |
|
||||
|---------|------|
|
||||
| `main.rs` | Point d'entrée, initialisation, lancement du worker |
|
||||
| `lib.rs` | `AppState` (pool, meili, api_base_url) |
|
||||
| `worker.rs` | Boucle principale : claim job → process → cleanup stale |
|
||||
| `job.rs` | `claim_next_job`, `process_job`, `fail_job`, `cleanup_stale_jobs` |
|
||||
| `scanner.rs` | Scan filesystem, parsing parallèle (rayon), batching DB |
|
||||
| `batch.rs` | `flush_all_batches` avec UNNEST, structures `BookInsert/Update/FileInsert/Update/ErrorInsert` |
|
||||
| `scheduler.rs` | Auto-scan : vérifie toutes les 60s les bibliothèques à monitorer |
|
||||
| `watcher.rs` | File watcher temps réel |
|
||||
| `meili.rs` | Indexation/sync Meilisearch |
|
||||
| `api.rs` | Appels HTTP vers l'API (pour checkup thumbnails) |
|
||||
| `utils.rs` | `remap_libraries_path`, `unmap_libraries_path`, `compute_fingerprint`, `kind_from_format` |
|
||||
|
||||
## Cycle de vie d'un job
|
||||
|
||||
```
|
||||
claim_next_job (UPDATE ... RETURNING, status pending→running)
|
||||
└─ process_job
|
||||
├─ scanner::scan_library (rayon par_iter pour le parsing)
|
||||
│ └─ flush_all_batches toutes les BATCH_SIZE=100 itérations
|
||||
└─ meili sync
|
||||
└─ api checkup thumbnails (POST /index/jobs/:id/thumbnails/checkup)
|
||||
```
|
||||
|
||||
- Annulation : `is_job_cancelled` vérifié toutes les 10 fichiers ou 1s — retourne `Err("Job cancelled")`
|
||||
- Jobs stale (running au redémarrage) → nettoyés par `cleanup_stale_jobs` au boot
|
||||
|
||||
## Pattern batch (batch.rs)
|
||||
|
||||
Toutes les opérations DB massives passent par `flush_all_batches` avec UNNEST :
|
||||
|
||||
```rust
|
||||
// Accumuler dans des Vec<BookInsert>, Vec<FileInsert>, etc.
|
||||
books_to_insert.push(BookInsert { ... });
|
||||
|
||||
// Flush quand plein ou en fin de scan
|
||||
if books_to_insert.len() >= BATCH_SIZE {
|
||||
flush_all_batches(&pool, &mut books_update, &mut files_update,
|
||||
&mut books_insert, &mut files_insert, &mut errors_insert).await?;
|
||||
}
|
||||
```
|
||||
|
||||
Toutes les opérations du flush sont dans une seule transaction.
|
||||
|
||||
## Scan filesystem (scanner.rs)
|
||||
|
||||
Pipeline en 3 étapes :
|
||||
1. **Collect** : WalkDir → filtrer par format (CBZ/CBR/PDF)
|
||||
2. **Parse** : `file_infos.into_par_iter().map(parse_metadata)` (rayon)
|
||||
3. **Process** : séquentiel pour les inserts/updates DB
|
||||
|
||||
Fingerprint = SHA256(taille + mtime) pour détecter les changements sans relire le fichier.
|
||||
|
||||
## Path remapping
|
||||
|
||||
```rust
|
||||
// abs_path en DB = chemin conteneur (/libraries/...)
|
||||
// Sur l'hôte : LIBRARIES_ROOT_PATH remplace /libraries
|
||||
utils::remap_libraries_path(&abs_path) // DB → filesystem local
|
||||
utils::unmap_libraries_path(&local_path) // filesystem local → DB
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Thumbnails** : générés par l'API après handoff, pas par l'indexer directement. L'indexer appelle `/index/jobs/:id/thumbnails/checkup` via `api.rs`.
|
||||
- **full_rebuild** : si `true`, ignore les fingerprints → tous les fichiers sont retraités.
|
||||
- **Annulation** : vérifier `is_job_cancelled` régulièrement pour respecter les annulations utilisateur.
|
||||
- **Watcher + scheduler** : tournent en tâches tokio séparées dans `worker.rs`, en parallèle de la boucle principale.
|
||||
Reference in New Issue
Block a user