Make the cache types compile time feature flags too, and make it more configurable!

This commit is contained in:
Zsombor Gegesy 2023-09-12 22:14:54 +02:00
parent 320f5f4720
commit 76795c43cc
7 changed files with 56 additions and 15 deletions

39
src/cache/cacher.rs vendored
View file

@ -2,30 +2,59 @@
//! from the upstream search engines in a json format.
use error_stack::Report;
#[cfg(feature = "in_memory_cache")]
use mini_moka::sync::Cache as MokaCache;
use std::time::Duration;
use tokio::sync::Mutex;
use crate::results::aggregation_models::SearchResults;
use crate::{config::parser::Config, results::aggregation_models::SearchResults};
use super::{error::PoolError, redis_cacher::RedisCache};
use super::error::PoolError;
#[cfg(feature = "redis")]
use super::redis_cacher::RedisCache;
/// Different implementations for caching, currently it is possible to cache in-memory or in Redis.
#[derive(Clone)]
pub enum Cache {
/// Caching is disabled
Disabled,
#[cfg(feature = "redis")]
/// Encapsulates the Redis based cache
Redis(RedisCache),
#[cfg(feature = "in_memory_cache")]
/// Contains the in-memory cache.
InMemory(MokaCache<String, SearchResults>),
}
impl Cache {
/// Builds the cache from the given configuration.
pub async fn build(config: &Config) -> Self {
#[cfg(feature = "redis")]
if let Some(url) = &config.redis_url {
log::info!("Using Redis running at {} for caching", &url);
return Cache::new(
RedisCache::new(url, 5)
.await
.expect("Redis cache configured"),
);
}
#[cfg(feature = "in_memory_cache")]
if config.in_memory_cache {
log::info!("Using an in-memory cache");
return Cache::new_in_memory();
}
log::info!("Caching is disabled");
Cache::Disabled
}
/// Creates a new cache, which wraps the given RedisCache.
#[cfg(feature = "redis")]
pub fn new(redis_cache: RedisCache) -> Self {
Cache::Redis(redis_cache)
}
/// Creates an in-memory cache
#[cfg(feature = "in_memory_cache")]
pub fn new_in_memory() -> Self {
let cache = MokaCache::builder()
.max_capacity(1000)
@ -41,11 +70,14 @@ impl Cache {
/// * `url` - It takes an url as a string.
pub async fn cached_json(&mut self, url: &str) -> Result<SearchResults, Report<PoolError>> {
match self {
Cache::Disabled => Err(Report::new(PoolError::MissingValue)),
#[cfg(feature = "redis")]
Cache::Redis(redis_cache) => {
let json = redis_cache.cached_json(url).await?;
Ok(serde_json::from_str::<SearchResults>(&json)
.map_err(|_| PoolError::SerializationError)?)
}
#[cfg(feature = "in_memory_cache")]
Cache::InMemory(in_memory) => match in_memory.get(&url.to_string()) {
Some(res) => Ok(res),
None => Err(Report::new(PoolError::MissingValue)),
@ -66,11 +98,14 @@ impl Cache {
url: &str,
) -> Result<(), Report<PoolError>> {
match self {
Cache::Disabled => Ok(()),
#[cfg(feature = "redis")]
Cache::Redis(redis_cache) => {
let json = serde_json::to_string(search_results)
.map_err(|_| PoolError::SerializationError)?;
redis_cache.cache_results(&json, url).await
}
#[cfg(feature = "in_memory_cache")]
Cache::InMemory(cache) => {
cache.insert(url.to_string(), search_results.clone());
Ok(())

3
src/cache/error.rs vendored
View file

@ -2,12 +2,14 @@
//! the redis server using an async connection pool.
use std::fmt;
#[cfg(feature = "redis")]
use redis::RedisError;
/// A custom error type used for handling redis async pool associated errors.
#[derive(Debug)]
pub enum PoolError {
/// This variant handles all errors related to `RedisError`,
#[cfg(feature = "redis")]
RedisError(RedisError),
/// This variant handles the errors which occurs when all the connections
/// in the connection pool return a connection dropped redis error.
@ -19,6 +21,7 @@ pub enum PoolError {
impl fmt::Display for PoolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
#[cfg(feature = "redis")]
PoolError::RedisError(redis_error) => {
if let Some(detail) = redis_error.detail() {
write!(f, "{}", detail)

1
src/cache/mod.rs vendored
View file

@ -3,4 +3,5 @@
pub mod cacher;
pub mod error;
#[cfg(feature = "redis")]
pub mod redis_cacher;