substrate/cache/
mod.rs

1//! Caching utilities.
2
3use std::{
4    any::Any,
5    sync::{Arc, Mutex},
6};
7
8use cache::{CacheHandle, Cacheable, CacheableWithState, mem::TypeCache, multi::MultiCache};
9use serde::{Serialize, de::DeserializeOwned};
10
11#[cfg(test)]
12mod tests;
13
14/// A cache with APIs for in-memory and persistent caching.
15#[derive(Default, Debug, Clone)]
16pub struct Cache {
17    inner: Arc<Mutex<CacheInner>>,
18}
19
20#[derive(Default, Debug)]
21struct CacheInner {
22    type_cache: TypeCache,
23    cache: MultiCache,
24}
25
26impl Cache {
27    /// Creates a new [`Cache`] with the provided [`MultiCache`] configuration.
28    pub fn new(cache: MultiCache) -> Self {
29        Self {
30            inner: Arc::new(Mutex::new(CacheInner {
31                type_cache: TypeCache::new(),
32                cache,
33            })),
34        }
35    }
36
37    /// Gets a handle to a cacheable object from the cache, generating the object in the background
38    /// if needed.
39    ///
40    /// If configured, persists data to disk.
41    ///
42    /// Does not cache errors, so any errors thrown should be thrown quickly. Any errors that need
43    /// to be cached should be included in the cached output or should be cached using
44    /// [`Cache::get_with_err`].
45    pub fn get<K: Cacheable>(
46        &self,
47        namespace: impl Into<String>,
48        key: K,
49    ) -> CacheHandle<Result<K::Output, K::Error>> {
50        let mut inner = self.inner.lock().unwrap();
51        inner.cache.get(namespace, key)
52    }
53
54    /// Gets a handle to a cacheable object from the cache, caching failures as well.
55    ///
56    /// Generates the object in the background if needed and persists data to disk according to
57    /// configuration.
58    pub fn get_with_err<
59        E: Send + Sync + Serialize + DeserializeOwned + Any,
60        K: Cacheable<Error = E>,
61    >(
62        &self,
63        namespace: impl Into<String>,
64        key: K,
65    ) -> CacheHandle<Result<K::Output, K::Error>> {
66        let mut inner = self.inner.lock().unwrap();
67        inner.cache.get_with_err(namespace, key)
68    }
69
70    /// Gets a handle to a cacheable object from the cache, generating the object in the background
71    /// if needed.
72    ///
73    /// If configured, persists data to disk.
74    ///
75    /// Does not cache errors, so any errors thrown should be thrown quickly. Any errors that need
76    /// to be cached should be included in the cached output or should be cached using
77    /// [`Cache::get_with_state_and_err`].
78    pub fn get_with_state<S: Send + Sync + Any, K: CacheableWithState<S>>(
79        &self,
80        namespace: impl Into<String>,
81        key: K,
82        state: S,
83    ) -> CacheHandle<Result<K::Output, K::Error>> {
84        let mut inner = self.inner.lock().unwrap();
85        inner.cache.get_with_state(namespace, key, state)
86    }
87
88    /// Gets a handle to a cacheable object from the cache, caching failures as well.
89    ///
90    /// Generates the object in the background if needed and persists data to disk according to
91    /// configuration.
92    ///
93    /// See [`Cache::get_with_err`] and [`Cache::get_with_state`] for related examples.
94    pub fn get_with_state_and_err<
95        S: Send + Sync + Any,
96        E: Send + Sync + Serialize + DeserializeOwned + Any,
97        K: CacheableWithState<S, Error = E>,
98    >(
99        &self,
100        namespace: impl Into<String>,
101        key: K,
102        state: S,
103    ) -> CacheHandle<Result<K::Output, K::Error>> {
104        let mut inner = self.inner.lock().unwrap();
105        inner.cache.get_with_state_and_err(namespace, key, state)
106    }
107
108    /// Gets a handle to a cacheable object from the cache, generating the object in the background
109    /// if needed.
110    ///
111    /// Only caches data in memory.
112    pub fn type_get<K: Cacheable>(
113        &self,
114        key: K,
115    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
116        let mut inner = self.inner.lock().unwrap();
117        inner.type_cache.generate(key, |key| key.generate())
118    }
119
120    /// Gets a handle to a cacheable object from the cache, generating the object in the background
121    /// if needed.
122    ///
123    /// Only caches data in memory.
124    ///
125    /// **Note:** The state is not used to determine whether the object should be regenerated. As
126    /// such, it should not impact the output of this function but rather should only be used to
127    /// store collateral or reuse computation from other function calls.
128    ///
129    /// However, the entries generated with different state types are not interchangeable. That is,
130    /// getting the same key with different states will regenerate the key several times, once for
131    /// each state type `S`.
132    pub fn type_get_with_state<S: Send + Sync + Any, K: CacheableWithState<S>>(
133        &self,
134        key: K,
135        state: S,
136    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
137        let mut inner = self.inner.lock().unwrap();
138        inner
139            .type_cache
140            .generate_with_state(key, state, |key, state| key.generate_with_state(state))
141    }
142}