refactoring des caches
This commit is contained in:
@@ -31,4 +31,5 @@ tracing = "0.1.41"
|
||||
|
||||
[features]
|
||||
default = ["pmoserver"]
|
||||
pmoserver = ["dep:pmoserver", "dep:pmoconfig", "dep:axum", "dep:utoipa", "pmocache/openapi", "pmocache/pmoserver"]
|
||||
pmoconfig = ["dep:pmoconfig", "pmocache/pmoconfig"]
|
||||
pmoserver = ["pmoconfig", "dep:pmoserver", "dep:axum", "dep:utoipa", "pmocache/openapi", "pmocache/pmoserver"]
|
||||
|
||||
106
pmocovers/src/config_ext.rs
Normal file
106
pmocovers/src/config_ext.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
//! Extension pour intégrer le cache de couvertures dans pmoconfig
|
||||
//!
|
||||
//! Ce module fournit le trait `CoverCacheConfigExt` qui permet d'ajouter facilement
|
||||
//! des méthodes de gestion du cache de couvertures à pmoconfig::Config.
|
||||
|
||||
use anyhow::Result;
|
||||
use pmoconfig::Config;
|
||||
use pmocache::CacheConfigExt;
|
||||
use std::sync::Arc;
|
||||
|
||||
const DEFAULT_COVER_CACHE_DIR: &str = "cache_covers";
|
||||
const DEFAULT_COVER_CACHE_SIZE: usize = 2000;
|
||||
|
||||
/// Trait d'extension pour gérer le cache de couvertures dans pmoconfig
|
||||
///
|
||||
/// Ce trait étend `pmoconfig::Config` avec des méthodes spécifiques
|
||||
/// au cache de couvertures avec conversion WebP.
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use pmoconfig::get_config;
|
||||
/// use pmocovers::CoverCacheConfigExt;
|
||||
///
|
||||
/// let config = get_config();
|
||||
/// let cache = config.create_cover_cache()?;
|
||||
///
|
||||
/// // Utiliser le cache
|
||||
/// let pk = cache.add_from_url("http://example.com/cover.jpg", Some("album:123")).await?;
|
||||
/// ```
|
||||
pub trait CoverCacheConfigExt {
|
||||
/// Récupère le répertoire du cache de couvertures
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Le chemin absolu du répertoire du cache de couvertures (default: "cache_covers")
|
||||
fn get_covers_dir(&self) -> Result<String>;
|
||||
|
||||
/// Définit le répertoire du cache de couvertures
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `directory` - Chemin du répertoire (absolu ou relatif au config_dir)
|
||||
fn set_covers_dir(&self, directory: String) -> Result<()>;
|
||||
|
||||
/// Récupère la taille maximale du cache de couvertures
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Le nombre maximal d'images dans le cache (default: 2000)
|
||||
fn get_covers_size(&self) -> Result<usize>;
|
||||
|
||||
/// Définit la taille maximale du cache de couvertures
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `size` - Nombre maximal d'images
|
||||
fn set_covers_size(&self, size: usize) -> Result<()>;
|
||||
|
||||
/// Crée une instance du cache de couvertures configurée avec conversion WebP
|
||||
///
|
||||
/// Cette méthode factory crée un cache de couvertures en utilisant les paramètres
|
||||
/// de configuration (répertoire et taille) et active la conversion WebP
|
||||
/// automatique pour toutes les images téléchargées.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Une instance Arc du cache de couvertures configuré
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use pmoconfig::get_config;
|
||||
/// use pmocovers::CoverCacheConfigExt;
|
||||
///
|
||||
/// let config = get_config();
|
||||
/// let cache = config.create_cover_cache()?;
|
||||
///
|
||||
/// // Le cache est prêt à être utilisé avec conversion WebP automatique
|
||||
/// ```
|
||||
fn create_cover_cache(&self) -> Result<Arc<crate::Cache>>;
|
||||
}
|
||||
|
||||
impl CoverCacheConfigExt for Config {
|
||||
fn get_covers_dir(&self) -> Result<String> {
|
||||
self.get_cache_dir("cover_cache", DEFAULT_COVER_CACHE_DIR)
|
||||
}
|
||||
|
||||
fn set_covers_dir(&self, directory: String) -> Result<()> {
|
||||
self.set_cache_dir("cover_cache", directory)
|
||||
}
|
||||
|
||||
fn get_covers_size(&self) -> Result<usize> {
|
||||
self.get_cache_size("cover_cache", DEFAULT_COVER_CACHE_SIZE)
|
||||
}
|
||||
|
||||
fn set_covers_size(&self, size: usize) -> Result<()> {
|
||||
self.set_cache_size("cover_cache", size)
|
||||
}
|
||||
|
||||
fn create_cover_cache(&self) -> Result<Arc<crate::Cache>> {
|
||||
let dir = self.get_covers_dir()?;
|
||||
let size = self.get_covers_size()?;
|
||||
Ok(Arc::new(crate::cache::new_cache(&dir, size)?))
|
||||
}
|
||||
}
|
||||
@@ -42,11 +42,17 @@ pub mod webp;
|
||||
#[cfg(feature = "pmoserver")]
|
||||
pub mod openapi;
|
||||
|
||||
#[cfg(feature = "pmoconfig")]
|
||||
pub mod config_ext;
|
||||
|
||||
pub use cache::{new_cache, Cache, CoversConfig};
|
||||
|
||||
#[cfg(feature = "pmoserver")]
|
||||
pub use openapi::ApiDoc;
|
||||
|
||||
#[cfg(feature = "pmoconfig")]
|
||||
pub use config_ext::CoverCacheConfigExt;
|
||||
|
||||
#[cfg(feature = "pmoserver")]
|
||||
use std::sync::Arc;
|
||||
#[cfg(feature = "pmoserver")]
|
||||
@@ -146,9 +152,10 @@ impl CoverCacheExt for pmoserver::Server {
|
||||
}
|
||||
|
||||
async fn init_cover_cache_configured(&mut self) -> anyhow::Result<Arc<Cache>> {
|
||||
use crate::CoverCacheConfigExt;
|
||||
let config = pmoconfig::get_config();
|
||||
let cache_dir = config.get_cover_cache_dir()?;
|
||||
let limit = config.get_cover_cache_size()?;
|
||||
let cache_dir = config.get_covers_dir()?;
|
||||
let limit = config.get_covers_size()?;
|
||||
self.init_cover_cache(&cache_dir, limit).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,25 @@ use anyhow::Result;
|
||||
use image::{imageops::FilterType, DynamicImage};
|
||||
use webp::{Encoder, WebPMemory};
|
||||
|
||||
/// Encode une image en format WebP avec un niveau de qualité de 85%
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `img` - Image à encoder
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Les données WebP encodées sous forme de vecteur d'octets
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use pmocovers::webp::encode_webp;
|
||||
/// use image::DynamicImage;
|
||||
///
|
||||
/// let img = DynamicImage::new_rgba8(100, 100);
|
||||
/// let webp_data = encode_webp(&img)?;
|
||||
/// ```
|
||||
pub fn encode_webp(img: &DynamicImage) -> Result<Vec<u8>> {
|
||||
let rgb_img = img.to_rgba8();
|
||||
let encoder = Encoder::from_rgba(&rgb_img, rgb_img.width(), rgb_img.height());
|
||||
@@ -9,6 +28,31 @@ pub fn encode_webp(img: &DynamicImage) -> Result<Vec<u8>> {
|
||||
Ok(webp_data.to_vec())
|
||||
}
|
||||
|
||||
/// Redimensionne une image pour l'inscrire dans un carré de taille donnée
|
||||
///
|
||||
/// Cette fonction préserve le ratio d'aspect de l'image originale en la redimensionnant
|
||||
/// pour qu'elle tienne dans un carré, puis la centre sur un fond transparent.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `img` - Image à redimensionner
|
||||
/// * `size` - Taille du carré de sortie (en pixels)
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Une nouvelle image carrée de taille `size × size` avec l'image originale centrée
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use pmocovers::webp::ensure_square;
|
||||
/// use image::DynamicImage;
|
||||
///
|
||||
/// let img = DynamicImage::new_rgba8(800, 600);
|
||||
/// let square = ensure_square(&img, 256);
|
||||
/// assert_eq!(square.width(), 256);
|
||||
/// assert_eq!(square.height(), 256);
|
||||
/// ```
|
||||
pub fn ensure_square(img: &DynamicImage, size: u32) -> DynamicImage {
|
||||
let (width, height) = (img.width(), img.height());
|
||||
|
||||
@@ -38,6 +82,36 @@ pub fn ensure_square(img: &DynamicImage, size: u32) -> DynamicImage {
|
||||
square
|
||||
}
|
||||
|
||||
/// Génère une variante redimensionnée d'une image en cache
|
||||
///
|
||||
/// Cette fonction crée (ou récupère si déjà existante) une variante redimensionnée
|
||||
/// d'une image. La variante est mise en cache sur disque pour éviter les
|
||||
/// recalculs futurs.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `cache` - Instance du cache de couvertures
|
||||
/// * `pk` - Clé primaire de l'image
|
||||
/// * `size` - Taille de la variante (carré de `size × size`)
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Les données WebP de la variante redimensionnée
|
||||
///
|
||||
/// # Comportement
|
||||
///
|
||||
/// 1. Si la variante existe déjà sur disque, elle est retournée directement
|
||||
/// 2. Sinon, l'image originale est chargée, redimensionnée et encodée en WebP
|
||||
/// 3. La variante est sauvegardée sur disque pour utilisation future
|
||||
///
|
||||
/// # Exemple
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use pmocovers::webp::generate_variant;
|
||||
///
|
||||
/// let cache = pmocovers::cache::new_cache("./cache", 1000)?;
|
||||
/// let variant_256 = generate_variant(&cache, "abc123", 256).await?;
|
||||
/// ```
|
||||
pub async fn generate_variant(
|
||||
cache: &super::cache::Cache,
|
||||
pk: &str,
|
||||
|
||||
Reference in New Issue
Block a user