- Ajout de `b.volume NULLS LAST` comme première clé de tri dans list_books
et dans tous les ROW_NUMBER() OVER (...) des CTEs series, pour corriger
l'ordre des volumes dont les titres varient en format (ex: "Round" vs "R")
- Suppression de l'ancienne extract_page publique et de ses 4 helpers
(extract_cbz_page_n, extract_cbz_page_n_streaming, extract_cbr_page_n,
extract_pdf_page_n) remplacés par la nouvelle implémentation avec cache
- Suppression de archive_index_cache dans AppState (remplacé par le cache
statique CBZ_INDEX_CACHE dans parsers), import StdMutex nettoyé
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chaque cold render ré-énumérait toutes les entrées ZIP/RAR pour construire
la liste triée des images. Maintenant la liste est mise en cache dans l'AppState
(LruCache<String, Arc<Vec<String>>>, std::sync::Mutex pour accès spawn_blocking).
Nouvelles fonctions dans parsers :
- list_archive_images(path, format) -> Vec<String>
- extract_image_by_name(path, format, name) -> Vec<u8>
Mesures avant/après (cache disque froid, n=20) :
- CBZ cold : 43ms → 11.9ms (-73%)
- CBR cold : 46ms → 11.0ms (-76%)
- Warm/concurrent : identique
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pages: mode Original (zero-transcoding), ETag/304, cache index CBZ,
préfetch next 2 pages, filtre Triangle par défaut
- Thumbnails: DCT scaling JPEG via jpeg-decoder (decode 7x plus rapide),
img.thumbnail() pour resize, support format Original, fix JPEG RGBA8
- API fallback thumbnail: OutputFormat::Original + DCT scaling au lieu
de WebP full-decode, retour (bytes, content_type) dynamique
- Watcher: remplacement notify par poll léger sans inotify/fd,
skip poll quand job actif, snapshots en mémoire
- Jobs: mutex exclusif corrigé (tous statuts actifs, tous types exclusifs)
- Robustesse: suppression fs::canonicalize (problèmes fd Docker),
list_folders avec erreurs explicites, has_children default true
- Backoffice: FormRow items-start pour alignement inputs avec helper text,
labels settings clarifiés
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Ajout de DynamicSettings dans AppState (Arc<RwLock>) chargé depuis la DB
- rate_limit_per_second, timeout_seconds : plus hardcodés, lus depuis settings
- image_processing (format, quality, filter, max_width) : appliqués comme
valeurs par défaut sur les requêtes de pages (overridables via query params)
- cache.directory : lu depuis settings au lieu de la variable d'env
- update_setting recharge immédiatement le DynamicSettings en mémoire
pour les clés limits, image_processing et cache (sans redémarrage)
- parse_filter() : mapping lanczos3/triangle/nearest → FilterType
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change all instances of AppState to reference the new state module across multiple files for consistency.
- Clean up imports in auth, books, index_jobs, libraries, pages, search, settings, thumbnails, and tokens modules.
- Simplify main.rs by removing unused code and organizing middleware and route handlers under the new handlers module.