| |
| |
|
|
| use error_stack::Report; |
| #[cfg(feature = "memory-cache")] |
| use mini_moka::sync::Cache as MokaCache; |
| #[cfg(feature = "memory-cache")] |
| use std::time::Duration; |
| use tokio::sync::Mutex; |
|
|
| use crate::{config::parser::Config, models::aggregation_models::SearchResults}; |
|
|
| use super::error::CacheError; |
| #[cfg(feature = "redis-cache")] |
| use super::redis_cacher::RedisCache; |
|
|
| |
| #[derive(Clone)] |
| pub enum Cache { |
| |
| Disabled, |
| #[cfg(all(feature = "redis-cache", not(feature = "memory-cache")))] |
| |
| Redis(RedisCache), |
| #[cfg(all(feature = "memory-cache", not(feature = "redis-cache")))] |
| |
| InMemory(MokaCache<String, SearchResults>), |
| #[cfg(all(feature = "redis-cache", feature = "memory-cache"))] |
| |
| Hybrid(RedisCache, MokaCache<String, SearchResults>), |
| } |
|
|
| impl Cache { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub async fn build(_config: &Config) -> Self { |
| #[cfg(all(feature = "redis-cache", feature = "memory-cache"))] |
| { |
| log::info!("Using a hybrid cache"); |
| Cache::new_hybrid( |
| RedisCache::new(&_config.redis_url, 5) |
| .await |
| .expect("Redis cache configured"), |
| ) |
| } |
| #[cfg(all(feature = "redis-cache", not(feature = "memory-cache")))] |
| { |
| log::info!("Listening redis server on {}", &_config.redis_url); |
| Cache::new( |
| RedisCache::new(&_config.redis_url, 5) |
| .await |
| .expect("Redis cache configured"), |
| ) |
| } |
| #[cfg(all(feature = "memory-cache", not(feature = "redis-cache")))] |
| { |
| log::info!("Using an in-memory cache"); |
| Cache::new_in_memory() |
| } |
| #[cfg(not(any(feature = "memory-cache", feature = "redis-cache")))] |
| { |
| log::info!("Caching is disabled"); |
| Cache::Disabled |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #[cfg(all(feature = "redis-cache", not(feature = "memory-cache")))] |
| pub fn new(redis_cache: RedisCache) -> Self { |
| Cache::Redis(redis_cache) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| #[cfg(all(feature = "memory-cache", not(feature = "redis-cache")))] |
| pub fn new_in_memory() -> Self { |
| let cache = MokaCache::builder() |
| .max_capacity(1000) |
| .time_to_live(Duration::from_secs(60)) |
| .build(); |
| Cache::InMemory(cache) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #[cfg(all(feature = "redis-cache", feature = "memory-cache"))] |
| pub fn new_hybrid(redis_cache: RedisCache) -> Self { |
| let cache = MokaCache::builder() |
| .max_capacity(1000) |
| .time_to_live(Duration::from_secs(60)) |
| .build(); |
| Cache::Hybrid(redis_cache, cache) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub async fn cached_json(&mut self, _url: &str) -> Result<SearchResults, Report<CacheError>> { |
| match self { |
| Cache::Disabled => Err(Report::new(CacheError::MissingValue)), |
| #[cfg(all(feature = "redis-cache", not(feature = "memory-cache")))] |
| Cache::Redis(redis_cache) => { |
| let json = redis_cache.cached_json(_url).await?; |
| Ok(serde_json::from_str::<SearchResults>(&json) |
| .map_err(|_| CacheError::SerializationError)?) |
| } |
| #[cfg(all(feature = "memory-cache", not(feature = "redis-cache")))] |
| Cache::InMemory(in_memory) => match in_memory.get(&_url.to_string()) { |
| Some(res) => Ok(res), |
| None => Err(Report::new(CacheError::MissingValue)), |
| }, |
| #[cfg(all(feature = "redis-cache", feature = "memory-cache"))] |
| Cache::Hybrid(redis_cache, in_memory) => match redis_cache.cached_json(_url).await { |
| Ok(res) => Ok(serde_json::from_str::<SearchResults>(&res) |
| .map_err(|_| CacheError::SerializationError)?), |
| Err(_) => match in_memory.get(&_url.to_string()) { |
| Some(res) => Ok(res), |
| None => Err(Report::new(CacheError::MissingValue)), |
| }, |
| }, |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub async fn cache_results( |
| &mut self, |
| _search_results: &SearchResults, |
| _url: &str, |
| ) -> Result<(), Report<CacheError>> { |
| match self { |
| Cache::Disabled => Ok(()), |
| #[cfg(all(feature = "redis-cache", not(feature = "memory-cache")))] |
| Cache::Redis(redis_cache) => { |
| let json = serde_json::to_string(_search_results) |
| .map_err(|_| CacheError::SerializationError)?; |
| redis_cache.cache_results(&json, _url).await |
| } |
| #[cfg(all(feature = "memory-cache", not(feature = "redis-cache")))] |
| Cache::InMemory(cache) => { |
| cache.insert(_url.to_string(), _search_results.clone()); |
| Ok(()) |
| } |
| #[cfg(all(feature = "memory-cache", feature = "redis-cache"))] |
| Cache::Hybrid(redis_cache, cache) => { |
| let json = serde_json::to_string(_search_results) |
| .map_err(|_| CacheError::SerializationError)?; |
| match redis_cache.cache_results(&json, _url).await { |
| Ok(_) => Ok(()), |
| Err(_) => { |
| cache.insert(_url.to_string(), _search_results.clone()); |
| Ok(()) |
| } |
| } |
| } |
| } |
| } |
| } |
|
|
| |
| pub struct SharedCache { |
| |
| cache: Mutex<Cache>, |
| } |
|
|
| impl SharedCache { |
| |
| |
| |
| |
| |
| |
| |
| pub fn new(cache: Cache) -> Self { |
| Self { |
| cache: Mutex::new(cache), |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub async fn cached_json(&self, url: &str) -> Result<SearchResults, Report<CacheError>> { |
| let mut mut_cache = self.cache.lock().await; |
| mut_cache.cached_json(url).await |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub async fn cache_results( |
| &self, |
| search_results: &SearchResults, |
| url: &str, |
| ) -> Result<(), Report<CacheError>> { |
| let mut mut_cache = self.cache.lock().await; |
| mut_cache.cache_results(search_results, url).await |
| } |
| } |
|
|