use parking_lot::RwLock;
use std::sync::Arc;
use std::time::Duration;
use super::persistent_store_wrapper::PersistentDataStoreWrapper;
use super::store_builders::{BuildError, DataStoreFactory};
use super::{persistent_store::PersistentDataStore, store::DataStore};
const DEFAULT_CACHE_TIME: Duration = Duration::from_secs(15);
pub trait PersistentDataStoreFactory {
fn create_persistent_data_store(&self) -> Result<Box<dyn PersistentDataStore>, std::io::Error>;
}
#[derive(Clone)]
pub struct PersistentDataStoreBuilder {
cache_ttl: Option<Duration>,
factory: Arc<dyn PersistentDataStoreFactory>,
}
impl PersistentDataStoreBuilder {
pub fn new(factory: Arc<dyn PersistentDataStoreFactory>) -> Self {
Self {
cache_ttl: Some(DEFAULT_CACHE_TIME),
factory,
}
}
pub fn cache_time(&mut self, cache_ttl: Duration) -> &mut Self {
self.cache_ttl = Some(cache_ttl);
self
}
pub fn cache_seconds(&mut self, seconds: u64) -> &mut Self {
self.cache_ttl = Some(Duration::from_secs(seconds));
self
}
pub fn cache_forever(&mut self) -> &mut Self {
self.cache_ttl = None;
self
}
pub fn no_caching(&mut self) -> &mut Self {
self.cache_ttl = Some(Duration::from_secs(0));
self
}
}
impl DataStoreFactory for PersistentDataStoreBuilder {
fn build(&self) -> Result<Arc<RwLock<dyn DataStore>>, BuildError> {
let store = self
.factory
.create_persistent_data_store()
.map_err(|e| BuildError::InvalidConfig(e.to_string()))?;
Ok(Arc::new(RwLock::new(PersistentDataStoreWrapper::new(
store,
self.cache_ttl,
))))
}
fn to_owned(&self) -> Box<dyn DataStoreFactory> {
Box::new(self.clone())
}
}
#[cfg(test)]
mod tests {
use crate::stores::persistent_store::tests::InMemoryPersistentDataStore;
use std::collections::HashMap;
use crate::stores::store_types::AllData;
use super::*;
struct InMemoryPersistentDataStoreFactory {}
impl PersistentDataStoreFactory for InMemoryPersistentDataStoreFactory {
fn create_persistent_data_store(
&self,
) -> Result<Box<dyn PersistentDataStore + 'static>, std::io::Error> {
Ok(Box::new(InMemoryPersistentDataStore {
data: AllData {
flags: HashMap::new(),
segments: HashMap::new(),
},
initialized: false,
}))
}
}
#[test]
fn builder_can_support_different_cache_ttl_options() {
let factory = InMemoryPersistentDataStoreFactory {};
let mut builder = PersistentDataStoreBuilder::new(Arc::new(factory));
assert_eq!(builder.cache_ttl, Some(DEFAULT_CACHE_TIME));
builder.cache_time(Duration::from_secs(100));
assert_eq!(builder.cache_ttl, Some(Duration::from_secs(100)));
builder.cache_seconds(1000);
assert_eq!(builder.cache_ttl, Some(Duration::from_secs(1000)));
builder.cache_forever();
assert_eq!(builder.cache_ttl, None);
}
}