Un fichier corrompu (RAR/ZIP/PDF qui ne répond plus) occupait un slot
de concurrence indéfiniment, bloquant le pipeline à ex. 1517/1521.
- Ajoute tokio::time::timeout autour de spawn_blocking(analyze_book)
- Timeout lu depuis limits.timeout_seconds en DB (défaut 120s)
- Le livre est marqué parse_status='error' en cas de timeout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Incremental rebuild: remplace le WalkDir de comptage par un COUNT(*) SQL
→ incrémental 67s → 25s (-62%) sur disque externe
- Full rebuild: conserve le WalkDir (DB vidée avant le comptage)
- Concurrence par défaut: num_cpus/2 clampé [2,8] au lieu de 2 fixe
- Ajoute num_cpus comme dépendance workspace
- Backoffice jobs: un seul formulaire avec formAction par bouton (icônes rétablies)
- infra/perf.sh: corrige l'endpoint /index/jobs/:id (pas /details), exporte BASE_API/TOKEN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cancel_job: ajouter 'extracting_pages' aux statuts annulables
- cleanup_stale_jobs: couvrir 'extracting_pages' et 'generating_thumbnails' au redémarrage
- analyzer: ne pas régénérer le thumbnail si déjà existant (skip sub-phase B)
- analyzer: supprimer les dotfiles macOS (._*) encore en DB
- SSE backoffice: réduire le spam de logs en cas d'API injoignable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added a new job status 'extracting_pages' to represent the first sub-phase of thumbnail generation.
- Updated the database schema to include a timestamp for when thumbnail generation starts.
- Enhanced job progress components to handle the new status, including UI updates for displaying progress and status labels.
- Refactored job-related logic to accommodate the two-phase process: extracting pages and generating thumbnails.
- Adjusted SQL queries and job detail responses to include the new fields and statuses.
This change improves the clarity of job processing states and enhances user feedback during the thumbnail generation process.
- CBR: contourner le bug XADRegexException de unar en appelant unar
avec un symlink à nom neutre (archive.cbr) au lieu du chemin réel,
qui peut contenir des caractères regex spéciaux comme [ ] ( )
- CBR/CBZ: remplacer le tri lexicographique par natord (tri naturel)
pour que page2.jpg soit trié avant page10.jpg
- PDF: brancher pdftoppm -scale-to sur config.width.max(config.height)
au lieu d'une valeur hardcodée (800px → 400px par défaut)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
L'analyzer ne vérifiait jamais le statut cancelled en DB, ce qui faisait
continuer le traitement des thumbnails jusqu'au bout, puis écraser le
statut 'cancelled' avec 'success'. Ajout d'un poller background toutes
les 2s avec AtomicBool partagé pour stopper proprement le stream concurrent.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cleanup_orphaned_thumbnails chargeait uniquement les book IDs de la library
en cours de rebuild, considérant les thumbnails des autres libraries comme
orphelins et les supprimant. La fonction charge désormais tous les book IDs
toutes libraries confondues.
Ajout d'un test de régression dans infra/smoke.sh qui vérifie que le
full_rebuild d'une library ne réduit pas le nombre de thumbnails des autres.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 1 (discovery): walkdir + filename-only metadata, zero archive I/O.
Books are visible immediately in the UI while Phase 2 runs in background.
Phase 2 (analysis): open each archive once via analyze_book() to extract
page_count and first page bytes, then generate WebP thumbnail directly in
the indexer — removing the HTTP roundtrip to the API checkup endpoint.
- Add parse_metadata_fast() (infallible, no archive I/O)
- Add analyze_book() returning (page_count, first_page_bytes) in one pass
- Add looks_like_image() magic bytes check for unrar p stdout validation
- Add lsar fallback in list_cbr_images() for UTF-16BE encoded filenames
- Add directory_mtimes table to skip unchanged dirs on incremental scans
- Add analyzer.rs: generate_thumbnail, analyze_library_books, regenerate_thumbnails
- Remove run_checkup() from API; indexer handles thumbnail jobs directly
- Remove api_base_url/api_bootstrap_token from IndexerConfig and AppState
- Add unar + poppler-utils to indexer Dockerfile
- Fix smoke.sh: wait for job completion, check thumbnail_url field
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>