launchdarkly_server_sdk/stores/
persistent_store_builders.rs1use parking_lot::RwLock;
2use std::sync::Arc;
3use std::time::Duration;
4
5use super::persistent_store_wrapper::PersistentDataStoreWrapper;
6use super::store_builders::{BuildError, DataStoreFactory};
7use super::{persistent_store::PersistentDataStore, store::DataStore};
8
9const DEFAULT_CACHE_TIME: Duration = Duration::from_secs(15);
10
11pub trait PersistentDataStoreFactory {
17 fn create_persistent_data_store(&self) -> Result<Box<dyn PersistentDataStore>, std::io::Error>;
19}
20
21#[derive(Clone)]
23pub struct PersistentDataStoreBuilder {
24 cache_ttl: Option<Duration>,
25 factory: Arc<dyn PersistentDataStoreFactory>,
26}
27
28impl PersistentDataStoreBuilder {
29 pub fn new(factory: Arc<dyn PersistentDataStoreFactory>) -> Self {
32 Self {
33 cache_ttl: Some(DEFAULT_CACHE_TIME),
34 factory,
35 }
36 }
37
38 pub fn cache_time(&mut self, cache_ttl: Duration) -> &mut Self {
43 self.cache_ttl = Some(cache_ttl);
44 self
45 }
46
47 pub fn cache_seconds(&mut self, seconds: u64) -> &mut Self {
49 self.cache_ttl = Some(Duration::from_secs(seconds));
50 self
51 }
52
53 pub fn cache_forever(&mut self) -> &mut Self {
62 self.cache_ttl = None;
63 self
64 }
65
66 pub fn no_caching(&mut self) -> &mut Self {
69 self.cache_ttl = Some(Duration::from_secs(0));
70 self
71 }
72}
73
74impl DataStoreFactory for PersistentDataStoreBuilder {
75 fn build(&self) -> Result<Arc<RwLock<dyn DataStore>>, BuildError> {
76 let store = self
77 .factory
78 .create_persistent_data_store()
79 .map_err(|e| BuildError::InvalidConfig(e.to_string()))?;
80 Ok(Arc::new(RwLock::new(PersistentDataStoreWrapper::new(
81 store,
82 self.cache_ttl,
83 ))))
84 }
85
86 fn to_owned(&self) -> Box<dyn DataStoreFactory> {
87 Box::new(self.clone())
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use crate::stores::persistent_store::tests::InMemoryPersistentDataStore;
94 use std::collections::HashMap;
95
96 use crate::stores::store_types::AllData;
97
98 use super::*;
99
100 struct InMemoryPersistentDataStoreFactory {}
101
102 impl PersistentDataStoreFactory for InMemoryPersistentDataStoreFactory {
103 fn create_persistent_data_store(
104 &self,
105 ) -> Result<Box<(dyn PersistentDataStore + 'static)>, std::io::Error> {
106 Ok(Box::new(InMemoryPersistentDataStore {
107 data: AllData {
108 flags: HashMap::new(),
109 segments: HashMap::new(),
110 },
111 initialized: false,
112 }))
113 }
114 }
115
116 #[test]
117 fn builder_can_support_different_cache_ttl_options() {
118 let factory = InMemoryPersistentDataStoreFactory {};
119 let mut builder = PersistentDataStoreBuilder::new(Arc::new(factory));
120
121 assert_eq!(builder.cache_ttl, Some(DEFAULT_CACHE_TIME));
122
123 builder.cache_time(Duration::from_secs(100));
124 assert_eq!(builder.cache_ttl, Some(Duration::from_secs(100)));
125
126 builder.cache_seconds(1000);
127 assert_eq!(builder.cache_ttl, Some(Duration::from_secs(1000)));
128
129 builder.cache_forever();
130 assert_eq!(builder.cache_ttl, None);
131 }
132}