File size: 4,988 Bytes
c170de8 db93c31 76795c4 996ff84 db93c31 76795c4 519ebe0 76795c4 c170de8 996ff84 1de52de 996ff84 76795c4 996ff84 76795c4 996ff84 519ebe0 c170de8 996ff84 76795c4 996ff84 76795c4 996ff84 c170de8 996ff84 76795c4 996ff84 c170de8 996ff84 c170de8 519ebe0 996ff84 76795c4 519ebe0 76795c4 996ff84 db93c31 c170de8 996ff84 c170de8 db93c31 3c7edb8 320f5f4 3c7edb8 db93c31 996ff84 76795c4 519ebe0 320f5f4 519ebe0 76795c4 996ff84 320f5f4 996ff84 c170de8 996ff84 c170de8 996ff84 db93c31 c170de8 996ff84 519ebe0 996ff84 519ebe0 996ff84 320f5f4 996ff84 519ebe0 996ff84 c170de8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
//! This module provides the functionality to cache the aggregated results fetched and aggregated
//! 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::{config::parser::Config, results::aggregation_models::SearchResults};
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)
.time_to_live(Duration::from_secs(60))
.build();
Cache::InMemory(cache)
}
/// A function which fetches the cached json results as json string.
///
/// # Arguments
///
/// * `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)),
},
}
}
/// A function which caches the results by using the `url` as the key and
/// `json results` as the value and stores it in the cache
///
/// # Arguments
///
/// * `json_results` - It takes the json results string as an argument.
/// * `url` - It takes the url as a String.
pub async fn cache_results(
&mut self,
search_results: &SearchResults,
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(())
}
}
}
}
/// A structure to efficiently share the cache between threads - as it is protected by a Mutex.
pub struct SharedCache {
cache: Mutex<Cache>,
}
impl SharedCache {
/// Creates a new SharedCache from a Cache implementation
pub fn new(cache: Cache) -> Self {
Self {
cache: Mutex::new(cache),
}
}
/// A function which retrieves the cached SearchResulsts from the internal cache.
pub async fn cached_json(&self, url: &str) -> Result<SearchResults, Report<PoolError>> {
let mut mut_cache = self.cache.lock().await;
mut_cache.cached_json(url).await
}
/// A function which caches the results by using the `url` as the key and
/// `SearchResults` as the value.
pub async fn cache_results(
&self,
search_results: &SearchResults,
url: &str,
) -> Result<(), Report<PoolError>> {
let mut mut_cache = self.cache.lock().await;
mut_cache.cache_results(search_results, url).await
}
}
|