launchdarkly_server_sdk/stores/
persistent_store_cache.rs

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
use std::collections::HashMap;
use std::hash::Hash;
use std::time::Duration;

use moka::sync::Cache;

use super::store_types::StorageItem;

pub(super) struct CachePair<T> {
    all: Cache<String, HashMap<String, StorageItem<T>>>,
    single: Cache<String, StorageItem<T>>,
    cache_name: String,
}

impl<T: 'static + Sync + Send + Clone> CachePair<T> {
    pub fn new(cache_name: String, cache_ttl: Option<Duration>) -> CachePair<T> {
        match cache_ttl {
            Some(ttl) => CachePair {
                all: Cache::builder().time_to_live(ttl).build(),
                single: Cache::builder().time_to_live(ttl).build(),
                cache_name,
            },
            None => CachePair {
                all: Cache::builder().build(),
                single: Cache::builder().build(),
                cache_name,
            },
        }
    }

    pub fn cache_is_infinite(&self) -> bool {
        self.all.policy().time_to_live().is_none()
    }

    pub fn get_all(&self) -> Option<HashMap<String, StorageItem<T>>> {
        self.all.get(&self.all_key())
    }

    pub fn get_one(&self, key: &str) -> Option<StorageItem<T>> {
        self.single.get(&self.single_key(key))
    }

    pub fn insert_single(&self, item: StorageItem<T>, key: &str) {
        self.insert_into_cache(&self.single, self.single_key(key), item)
    }

    pub fn insert_all(&self, data: HashMap<String, StorageItem<T>>) {
        self.insert_into_cache(&self.all, self.all_key(), data)
    }

    fn insert_into_cache<K, V>(&self, cache: &Cache<K, V>, key: K, value: V)
    where
        K: Hash + Eq + Send + Sync + 'static,
        V: Clone + Send + Sync + 'static,
    {
        match cache.policy().time_to_live() {
            None => cache.insert(key, value),
            Some(duration) if !duration.is_zero() => cache.insert(key, value),
            _ => (),
        }
    }

    fn all_key(&self) -> String {
        format!("all:{}", self.cache_name)
    }

    fn single_key(&self, key: &str) -> String {
        format!("{}:{}", self.cache_name, key)
    }

    pub fn invalidate_all(&self) {
        self.all.invalidate_all();
    }

    pub fn invalidate_single(&self, key: &str) {
        self.single.invalidate(&self.single_key(key));
    }

    pub fn invalidate_everything(&self) {
        self.all.invalidate_all();
        self.single.invalidate_all();
    }
}