cache/
mem.rs

1//! In-memory caching utilities.
2
3use std::{
4    any::{Any, TypeId},
5    collections::{HashMap, hash_map::Entry},
6    fmt::Debug,
7    hash::Hash,
8    sync::Arc,
9    thread,
10};
11
12use serde::{Serialize, de::DeserializeOwned};
13
14use crate::{
15    CacheHandle, CacheHandleInner, CacheValueHolder, Cacheable, CacheableWithState, GenerateFn,
16    GenerateResultFn, GenerateResultWithStateFn, GenerateWithStateFn, Namespace, error::ArcResult,
17    run_generator,
18};
19
20#[derive(Debug)]
21struct TypeMapInner<T> {
22    /// Effectively a map from `T -> HashMap<K, V>`.
23    entries: HashMap<T, Box<dyn Any + Send + Sync>>,
24}
25
26impl<T> Default for TypeMapInner<T> {
27    fn default() -> Self {
28        Self {
29            entries: HashMap::new(),
30        }
31    }
32}
33
34impl<T: Hash + PartialEq + Eq> TypeMapInner<T> {
35    fn get_or_insert<K: Hash + Eq + Any + Send + Sync, V: Any + Send + Sync>(
36        &mut self,
37        namespace: T,
38        key: K,
39        f: impl FnOnce() -> V,
40    ) -> &V {
41        let entry = self
42            .entries
43            .entry(namespace)
44            .or_insert_with(|| Box::<HashMap<K, V>>::default());
45
46        entry
47            .downcast_mut::<HashMap<K, V>>()
48            .unwrap()
49            .entry(key)
50            .or_insert_with(f)
51    }
52}
53
54#[derive(Debug)]
55struct TypeCacheInner<T> {
56    /// A map from key type to another map from key to value handle.
57    ///
58    /// Effectively, the type of this map is `TypeId::of::<K>() -> HashMap<Arc<K>, (V1, Arc<OnceCell<Result<V2, E>>)>`.
59    partial_blocking_map: TypeMapInner<T>,
60    /// A map from key type to another map from key to value handle.
61    ///
62    /// Effectively, the type of this map is `TypeId::of::<K>() -> HashMap<Arc<K>, Arc<OnceCell<Result<V, E>>>`.
63    map: TypeMapInner<T>,
64}
65
66impl<T> Default for TypeCacheInner<T> {
67    fn default() -> Self {
68        Self {
69            partial_blocking_map: TypeMapInner::default(),
70            map: TypeMapInner::default(),
71        }
72    }
73}
74
75impl<T: Hash + PartialEq + Eq> TypeCacheInner<T> {
76    fn generate_blocking<K: Hash + Eq + Any + Send + Sync, V: Send + Sync + Any>(
77        &mut self,
78        namespace: T,
79        key: K,
80        generate_fn: impl GenerateFn<K, V>,
81    ) -> &V {
82        let key = Arc::new(key);
83        self.map
84            .get_or_insert(namespace, key.clone(), move || {
85                CacheHandle::new_blocking(move || generate_fn(key.as_ref()))
86            })
87            .get()
88    }
89
90    fn generate_partial_blocking<
91        K: Hash + Eq + Any + Send + Sync,
92        V1: Send + Sync + Any,
93        V2: Send + Sync + Any,
94        S: Send + Sync + Any,
95    >(
96        &mut self,
97        namespace: T,
98        key: K,
99        blocking_generate_fn: impl FnOnce(&K) -> (V1, S),
100        generate_fn: impl GenerateWithStateFn<K, S, V2>,
101    ) -> (&V1, CacheHandle<V2>) {
102        let key = Arc::new(key);
103        let (v1, handle) =
104            self.partial_blocking_map
105                .get_or_insert(namespace, key.clone(), move || {
106                    let (v1, s) = blocking_generate_fn(key.as_ref());
107                    (v1, CacheHandle::new(move || generate_fn(key.as_ref(), s)))
108                });
109        (v1, handle.clone())
110    }
111
112    fn generate<K: Hash + Eq + Any + Send + Sync, V: Send + Sync + Any>(
113        &mut self,
114        namespace: T,
115        key: K,
116        generate_fn: impl GenerateFn<K, V>,
117    ) -> CacheHandle<V> {
118        let key = Arc::new(key);
119        self.map
120            .get_or_insert(namespace, key.clone(), move || {
121                CacheHandle::new(move || generate_fn(key.as_ref()))
122            })
123            .clone()
124    }
125}
126
127/// An in-memory cache based on hashable types.
128#[derive(Default, Debug)]
129pub struct TypeCache {
130    inner: TypeCacheInner<TypeId>,
131    inner_with_state: TypeCacheInner<(TypeId, TypeId)>,
132}
133
134impl TypeCache {
135    /// Creates a new cache.
136    pub fn new() -> Self {
137        Self::default()
138    }
139
140    /// The blocking equivalent of [`TypeCache::generate`].
141    pub fn generate_blocking<K: Hash + Eq + Any + Send + Sync, V: Send + Sync + Any>(
142        &mut self,
143        key: K,
144        generate_fn: impl GenerateFn<K, V>,
145    ) -> &V {
146        self.inner
147            .generate_blocking(TypeId::of::<K>(), key, generate_fn)
148    }
149
150    /// Blocks on generating a portion `V1` of the cached value as in [`TypeCache::generate_blocking`],
151    /// then generates the remainder `V2` in the background as in [`TypeCache::generate`].
152    ///
153    /// Accesses a separate cache from [`TypeCache::generate_blocking`] and [`TypeCache::generate`].
154    /// That is, a key being accessed with this method will not affect the set of available
155    /// key-value pairs for the other two methods.
156    pub fn generate_partial_blocking<
157        K: Hash + Eq + Any + Send + Sync,
158        V1: Send + Sync + Any,
159        V2: Send + Sync + Any,
160        S: Send + Sync + Any,
161    >(
162        &mut self,
163        key: K,
164        blocking_generate_fn: impl FnOnce(&K) -> (V1, S),
165        generate_fn: impl GenerateWithStateFn<K, S, V2>,
166    ) -> (&V1, CacheHandle<V2>) {
167        self.inner.generate_partial_blocking(
168            TypeId::of::<K>(),
169            key,
170            blocking_generate_fn,
171            generate_fn,
172        )
173    }
174
175    /// Ensures that a value corresponding to `key` is generated, using `generate_fn`
176    /// to generate it if it has not already been generated.
177    ///
178    /// A more general counterpart to [`TypeCache::get`].
179    ///
180    /// Returns a handle to the value. If the value is not yet generated, it is generated
181    /// in the background.
182    ///
183    /// # Panics
184    ///
185    /// Panics if a different type `V` or `E` is already associated with type `K`.
186    ///
187    /// # Examples
188    ///
189    /// ```
190    /// use std::sync::{Arc, Mutex};
191    /// use cache::{mem::TypeCache, error::Error, CacheableWithState};
192    ///
193    /// let mut cache = TypeCache::new();
194    ///
195    /// fn generate_fn(tuple: &(u64, u64)) -> u64 {
196    ///     tuple.0 + tuple.1
197    /// }
198    ///
199    /// let handle = cache.generate((5, 6), generate_fn);
200    /// assert_eq!(*handle.get(), 11);
201    ///
202    /// // Does not call `generate_fn` again as the result has been cached.
203    /// let handle = cache.generate((5, 6), generate_fn);
204    /// assert_eq!(*handle.get(), 11);
205    /// ```
206    pub fn generate<K: Hash + Eq + Any + Send + Sync, V: Send + Sync + Any>(
207        &mut self,
208        key: K,
209        generate_fn: impl GenerateFn<K, V>,
210    ) -> CacheHandle<V> {
211        self.inner.generate(TypeId::of::<K>(), key, generate_fn)
212    }
213
214    /// The blocking equivalent of [`TypeCache::generate_with_state`].
215    pub fn generate_with_state_blocking<
216        K: Hash + Eq + Any + Send + Sync,
217        V: Send + Sync + Any,
218        S: Send + Sync + Any,
219    >(
220        &mut self,
221        key: K,
222        state: S,
223        generate_fn: impl GenerateWithStateFn<K, S, V>,
224    ) -> &V {
225        self.inner_with_state.generate_blocking(
226            (TypeId::of::<K>(), TypeId::of::<S>()),
227            key,
228            move |key| generate_fn(key, state),
229        )
230    }
231
232    /// Ensures that a value corresponding to `key` is generated, using `generate_fn`
233    /// to generate it if it has not already been generated.
234    ///
235    /// A more general counterpart to [`TypeCache::get_with_state`].
236    ///
237    /// Returns a handle to the value. If the value is not yet generated, it is generated
238    /// in the background.
239    ///
240    /// # Panics
241    ///
242    /// Panics if a different type `V` or `E` is already associated with type `K`.
243    ///
244    /// # Examples
245    ///
246    /// ```
247    /// use std::sync::{Arc, Mutex};
248    /// use cache::{mem::TypeCache, error::Error, CacheableWithState};
249    ///
250    /// #[derive(Clone)]
251    /// pub struct Log(Arc<Mutex<Vec<(u64, u64)>>>);
252    ///
253    /// let mut cache = TypeCache::new();
254    /// let log = Log(Arc::new(Mutex::new(Vec::new())));
255    ///
256    /// fn generate_fn(tuple: &(u64, u64), state: Log) -> u64 {
257    ///     println!("Logging parameters...");
258    ///     state.0.lock().unwrap().push(*tuple);
259    ///     tuple.0 + tuple.1
260    /// }
261    ///
262    /// let handle = cache.generate_with_state((5, 6), log.clone(), generate_fn);
263    /// assert_eq!(*handle.get(), 11);
264    ///
265    /// // Does not call `generate_fn` again as the result has been cached.
266    /// let handle = cache.generate_with_state((5, 6), log.clone(), generate_fn);
267    /// assert_eq!(*handle.get(), 11);
268    ///
269    /// assert_eq!(log.0.lock().unwrap().clone(), vec![(5, 6)]);
270    /// ```
271    pub fn generate_with_state<
272        K: Hash + Eq + Any + Send + Sync,
273        V: Send + Sync + Any,
274        S: Send + Sync + Any,
275    >(
276        &mut self,
277        key: K,
278        state: S,
279        generate_fn: impl GenerateWithStateFn<K, S, V>,
280    ) -> CacheHandle<V> {
281        self.inner_with_state
282            .generate((TypeId::of::<K>(), TypeId::of::<S>()), key, move |key| {
283                generate_fn(key, state)
284            })
285    }
286
287    /// The blocking equivalent of [`TypeCache::get`].
288    pub fn get_blocking<K: Cacheable>(
289        &mut self,
290        key: K,
291    ) -> &std::result::Result<K::Output, K::Error> {
292        self.generate_blocking(key, |key| key.generate())
293    }
294
295    /// Gets a handle to a cacheable object from the cache, generating the object in the background
296    /// if needed.
297    ///
298    /// # Examples
299    ///
300    /// ```
301    /// use cache::{mem::TypeCache, error::Error, Cacheable};
302    /// use serde::{Deserialize, Serialize};
303    ///
304    /// #[derive(Deserialize, Serialize, Hash, Eq, PartialEq)]
305    /// pub struct Params {
306    ///     param1: u64,
307    ///     param2: String,
308    /// };
309    ///
310    /// impl Cacheable for Params {
311    ///     type Output = u64;
312    ///     type Error = anyhow::Error;
313    ///
314    ///     fn generate(&self) -> anyhow::Result<u64> {
315    ///         if self.param1 == 5 {
316    ///             anyhow::bail!("invalid param");
317    ///         } else if &self.param2 == "panic" {
318    ///             panic!("unrecoverable param");
319    ///         }
320    ///         Ok(2 * self.param1)
321    ///     }
322    /// }
323    ///
324    /// let mut cache = TypeCache::new();
325    ///
326    /// let handle = cache.get(Params { param1: 50, param2: "cache".to_string() });
327    /// assert_eq!(*handle.unwrap_inner(), 100);
328    ///
329    /// let handle = cache.get(Params { param1: 5, param2: "cache".to_string() });
330    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid param");
331    ///
332    /// let handle = cache.get(Params { param1: 50, param2: "panic".to_string() });
333    /// assert!(matches!(handle.get_err().as_ref(), Error::Panic));
334    /// ```
335    pub fn get<K: Cacheable>(
336        &mut self,
337        key: K,
338    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
339        self.generate(key, |key| key.generate())
340    }
341
342    /// The blocking equivalent of [`TypeCache::get_with_state`].
343    pub fn get_with_state_blocking<S: Send + Sync + Any, K: CacheableWithState<S>>(
344        &mut self,
345        key: K,
346        state: S,
347    ) -> &std::result::Result<K::Output, K::Error> {
348        self.generate_with_state_blocking(key, state, |key, state| key.generate_with_state(state))
349    }
350
351    /// Gets a handle to a cacheable object from the cache, generating the object in the background
352    /// if needed.
353    ///
354    /// **Note:** The state is not used to determine whether the object should be regenerated. As
355    /// such, it should not impact the output of this function but rather should only be used to
356    /// store collateral or reuse computation from other function calls.
357    ///
358    /// However, the entries generated with different state types are not interchangeable. That is,
359    /// getting the same key with different states will regenerate the key several times, once for
360    /// each state type `S`.
361    ///
362    /// # Examples
363    ///
364    /// ```
365    /// use std::sync::{Arc, Mutex};
366    /// use cache::{mem::TypeCache, error::Error, CacheableWithState};
367    /// use serde::{Deserialize, Serialize};
368    ///
369    /// #[derive(Debug, Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
370    /// pub struct Params(u64);
371    ///
372    /// #[derive(Clone)]
373    /// pub struct Log(Arc<Mutex<Vec<Params>>>);
374    ///
375    /// impl CacheableWithState<Log> for Params {
376    ///     type Output = u64;
377    ///     type Error = anyhow::Error;
378    ///
379    ///     fn generate_with_state(&self, state: Log) -> anyhow::Result<u64> {
380    ///         println!("Logging parameters...");
381    ///         state.0.lock().unwrap().push(self.clone());
382    ///
383    ///         if self.0 == 5 {
384    ///             anyhow::bail!("invalid param");
385    ///         } else if self.0 == 8 {
386    ///             panic!("unrecoverable param");
387    ///         }
388    ///         Ok(2 * self.0)
389    ///     }
390    /// }
391    ///
392    /// let mut cache = TypeCache::new();
393    /// let log = Log(Arc::new(Mutex::new(Vec::new())));
394    ///
395    /// let handle = cache.get_with_state(Params(0), log.clone());
396    /// assert_eq!(*handle.unwrap_inner(), 0);
397    ///
398    /// let handle = cache.get_with_state(Params(5), log.clone());
399    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid param");
400    ///
401    /// let handle = cache.get_with_state(Params(8), log.clone());
402    /// assert!(matches!(handle.get_err().as_ref(), Error::Panic));
403    ///
404    /// assert_eq!(log.0.lock().unwrap().clone(), vec![Params(0), Params(5), Params(8)]);
405    /// ```
406    pub fn get_with_state<S: Send + Sync + Any, K: CacheableWithState<S>>(
407        &mut self,
408        key: K,
409        state: S,
410    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
411        self.generate_with_state(key, state, |key, state| key.generate_with_state(state))
412    }
413}
414
415/// Maps from a key to a handle on a value that may be set to [`None`] if the generator returns an
416/// uncacheable result. In this case, the result must be regenerated each time.
417type NamespaceEntryMap = HashMap<Vec<u8>, CacheHandleInner<Option<Vec<u8>>>>;
418
419/// Serializes the provided value to bytes, returning [`None`] if the value should not be cached.
420trait SerializeValueFn<V>: FnOnce(&V) -> Option<Vec<u8>> + Send + Any {}
421impl<V, T: FnOnce(&V) -> Option<Vec<u8>> + Send + Any> SerializeValueFn<V> for T {}
422
423/// Deserializes desired value from bytes stored in the cache. If `V` is a result, would need to
424/// wrap the bytes from the cache with an `Ok` since `Err` results are not stored in the cache.
425trait DeserializeValueFn<V>: FnOnce(&[u8]) -> ArcResult<V> + Send + Any {}
426impl<V, T: FnOnce(&[u8]) -> ArcResult<V> + Send + Any> DeserializeValueFn<V> for T {}
427
428/// An in-memory cache based on namespace strings and types that implement [`Serialize`] and
429/// [`Deserialize`](serde::Deserialize).
430///
431/// Unlike a [`TypeCache`], a [`NamespaceCache`] works by serializing and deserializing keys and
432/// values. As such, an entry can be accessed with several generic types as long as all of the
433/// types serialize/deserialize to/from the same bytes.
434#[derive(Default, Debug, Clone)]
435pub struct NamespaceCache {
436    /// A map from namespace to another map from key to value handle.
437    entries: HashMap<Namespace, NamespaceEntryMap>,
438}
439
440impl NamespaceCache {
441    /// Creates a new cache.
442    pub fn new() -> Self {
443        Self::default()
444    }
445
446    /// Ensures that a value corresponding to `key` is generated, using `generate_fn`
447    /// to generate it if it has not already been generated.
448    ///
449    /// A more general counterpart to [`NamespaceCache::get`].
450    ///
451    /// Returns a handle to the value. If the value is not yet generated, it is generated
452    /// in the background.
453    ///
454    /// # Panics
455    ///
456    /// Panics if a different type `V` or `E` is already associated with type `K`.
457    ///
458    /// # Examples
459    ///
460    /// ```
461    /// use cache::{mem::NamespaceCache, error::Error, CacheableWithState};
462    ///
463    /// let mut cache = NamespaceCache::new();
464    ///
465    /// fn generate_fn(tuple: &(u64, u64)) -> u64 {
466    ///     tuple.0 + tuple.1
467    /// }
468    ///
469    /// fn generate_fn2(tuple: &(u64, u64)) -> u64 {
470    ///     tuple.0 * tuple.1
471    /// }
472    ///
473    /// let handle = cache.generate("example.namespace", (5, 6), generate_fn);
474    /// assert_eq!(*handle.get(), 11);
475    ///
476    /// // Does not call `generate_fn` again as the result has been cached.
477    /// let handle = cache.generate("example.namespace", (5, 6), generate_fn);
478    /// assert_eq!(*handle.get(), 11);
479    ///
480    /// // Calls the new `generate_fn2` as the namespace is different,
481    /// // even though the key is the same.
482    /// let handle = cache.generate("example.namespace2", (5, 6), generate_fn2);
483    /// assert_eq!(*handle.get(), 30);
484    /// ```
485    pub fn generate<
486        K: Serialize + Any + Send + Sync,
487        V: Serialize + DeserializeOwned + Send + Sync + Any,
488    >(
489        &mut self,
490        namespace: impl Into<Namespace>,
491        key: K,
492        generate_fn: impl GenerateFn<K, V>,
493    ) -> CacheHandle<V> {
494        CacheHandle::from_inner(Arc::new(self.generate_inner(namespace, key, generate_fn)))
495    }
496
497    /// Ensures that a value corresponding to `key` is generated, using `generate_fn`
498    /// to generate it if it has not already been generated.
499    ///
500    /// A more general counterpart to [`NamespaceCache::get_with_state`].
501    ///
502    /// Returns a handle to the value. If the value is not yet generated, it is generated
503    /// in the background.
504    ///
505    /// # Panics
506    ///
507    /// Panics if a different type `V` or `E` is already associated with type `K`.
508    ///
509    /// # Examples
510    ///
511    /// ```
512    /// use std::sync::{Arc, Mutex};
513    /// use cache::{mem::NamespaceCache, error::Error, CacheableWithState};
514    ///
515    /// #[derive(Clone)]
516    /// pub struct Log(Arc<Mutex<Vec<(u64, u64)>>>);
517    ///
518    /// let mut cache = NamespaceCache::new();
519    /// let log = Log(Arc::new(Mutex::new(Vec::new())));
520    ///
521    /// fn generate_fn(tuple: &(u64, u64), state: Log) -> u64 {
522    ///     println!("Logging parameters...");
523    ///     state.0.lock().unwrap().push(*tuple);
524    ///     tuple.0 + tuple.1
525    /// }
526    ///
527    /// let handle = cache.generate_with_state("example.namespace", (5, 6), log.clone(), generate_fn);
528    /// assert_eq!(*handle.get(), 11);
529    ///
530    /// // Does not call `generate_fn` again as the result has been cached.
531    /// let handle = cache.generate_with_state("example.namespace", (5, 6), log.clone(), generate_fn);
532    /// assert_eq!(*handle.get(), 11);
533    ///
534    /// assert_eq!(log.0.lock().unwrap().clone(), vec![(5, 6)]);
535    /// ```
536    pub fn generate_with_state<
537        K: Serialize + Any + Send + Sync,
538        V: Serialize + DeserializeOwned + Send + Sync + Any,
539        S: Send + Sync + Any,
540    >(
541        &mut self,
542        namespace: impl Into<Namespace>,
543        key: K,
544        state: S,
545        generate_fn: impl GenerateWithStateFn<K, S, V>,
546    ) -> CacheHandle<V> {
547        let namespace = namespace.into();
548        self.generate(namespace, key, |key| generate_fn(key, state))
549    }
550
551    /// Ensures that a result corresponding to `key` is generated, using `generate_fn`
552    /// to generate it if it has not already been generated.
553    ///
554    /// Does not cache on failure as errors are not constrained to be serializable/deserializable.
555    /// As such, failures should happen quickly, or should be serializable and stored as part of
556    /// cached value using [`NamespaceCache::generate`].
557    ///
558    /// Returns a handle to the value. If the value is not yet generated, it is generated
559    ///
560    /// # Examples
561    ///
562    /// ```
563    /// use cache::{mem::NamespaceCache, error::Error, Cacheable};
564    ///
565    /// let mut cache = NamespaceCache::new();
566    ///
567    /// fn generate_fn(tuple: &(u64, u64)) -> anyhow::Result<u64> {
568    ///     if *tuple == (5, 5) {
569    ///         Err(anyhow::anyhow!("invalid tuple"))
570    ///     } else {
571    ///         Ok(tuple.0 + tuple.1)
572    ///     }
573    /// }
574    ///
575    /// let handle = cache.generate_result("example.namespace", (5, 5), generate_fn);
576    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid tuple");
577    ///
578    /// // Calls `generate_fn` again as the error was not cached.
579    /// let handle = cache.generate_result("example.namespace", (5, 5), generate_fn);
580    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid tuple");
581    /// ```
582    pub fn generate_result<
583        K: Serialize + Any + Send + Sync,
584        V: Serialize + DeserializeOwned + Send + Sync + Any,
585        E: Send + Sync + Any,
586    >(
587        &mut self,
588        namespace: impl Into<Namespace>,
589        key: K,
590        generate_fn: impl GenerateResultFn<K, V, E>,
591    ) -> CacheHandle<std::result::Result<V, E>> {
592        CacheHandle::from_inner(Arc::new(self.generate_result_inner(
593            namespace,
594            key,
595            generate_fn,
596        )))
597    }
598
599    /// Ensures that a value corresponding to `key` is generated, using `generate_fn`
600    /// to generate it if it has not already been generated.
601    ///
602    /// Does not cache on failure as errors are not constrained to be serializable/deserializable.
603    /// As such, failures should happen quickly, or should be serializable and stored as part of
604    /// cached value using [`NamespaceCache::generate_with_state`].
605    ///
606    /// Returns a handle to the value. If the value is not yet generated, it is generated
607    /// in the background.
608    ///
609    /// # Examples
610    ///
611    /// ```
612    /// use std::sync::{Arc, Mutex};
613    /// use cache::{mem::NamespaceCache, error::Error, Cacheable};
614    ///
615    /// #[derive(Clone)]
616    /// pub struct Log(Arc<Mutex<Vec<(u64, u64)>>>);
617    ///
618    /// let mut cache = NamespaceCache::new();
619    /// let log = Log(Arc::new(Mutex::new(Vec::new())));
620    ///
621    /// fn generate_fn(tuple: &(u64, u64), state: Log) -> anyhow::Result<u64> {
622    ///     println!("Logging parameters...");
623    ///     state.0.lock().unwrap().push(*tuple);
624    ///
625    ///     if *tuple == (5, 5) {
626    ///         Err(anyhow::anyhow!("invalid tuple"))
627    ///     } else {
628    ///         Ok(tuple.0 + tuple.1)
629    ///     }
630    /// }
631    ///
632    /// let handle = cache.generate_result_with_state(
633    ///     "example.namespace", (5, 5), log.clone(), generate_fn
634    /// );
635    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid tuple");
636    ///
637    /// // Calls `generate_fn` again as the error was not cached.
638    /// let handle = cache.generate_result_with_state(
639    ///     "example.namespace", (5, 5), log.clone(), generate_fn
640    /// );
641    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid tuple");
642    ///
643    /// assert_eq!(log.0.lock().unwrap().clone(), vec![(5, 5), (5, 5)]);
644    /// ```
645    pub fn generate_result_with_state<
646        K: Serialize + Send + Sync + Any,
647        V: Serialize + DeserializeOwned + Send + Sync + Any,
648        E: Send + Sync + Any,
649        S: Send + Sync + Any,
650    >(
651        &mut self,
652        namespace: impl Into<Namespace>,
653        key: K,
654        state: S,
655        generate_fn: impl GenerateResultWithStateFn<K, S, V, E>,
656    ) -> CacheHandle<std::result::Result<V, E>> {
657        let namespace = namespace.into();
658        self.generate_result(namespace, key, move |k| generate_fn(k, state))
659    }
660
661    /// Gets a handle to a cacheable object from the cache, generating the object in the background
662    /// if needed.
663    ///
664    /// # Examples
665    ///
666    /// ```
667    /// use cache::{mem::NamespaceCache, error::Error, Cacheable};
668    /// use serde::{Deserialize, Serialize};
669    ///
670    /// #[derive(Deserialize, Serialize, Hash, Eq, PartialEq)]
671    /// pub struct Params {
672    ///     param1: u64,
673    ///     param2: String,
674    /// };
675    ///
676    /// impl Cacheable for Params {
677    ///     type Output = u64;
678    ///     type Error = anyhow::Error;
679    ///
680    ///     fn generate(&self) -> anyhow::Result<u64> {
681    ///         if self.param1 == 5 {
682    ///             anyhow::bail!("invalid param");
683    ///         } else if &self.param2 == "panic" {
684    ///             panic!("unrecoverable param");
685    ///         }
686    ///         Ok(2 * self.param1)
687    ///     }
688    /// }
689    ///
690    /// let mut cache = NamespaceCache::new();
691    ///
692    /// let handle = cache.get(
693    ///     "example.namespace", Params { param1: 50, param2: "cache".to_string() }
694    /// );
695    /// assert_eq!(*handle.unwrap_inner(), 100);
696    ///
697    /// let handle = cache.get(
698    ///     "example.namespace", Params { param1: 5, param2: "cache".to_string() }
699    /// );
700    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid param");
701    ///
702    /// let handle = cache.get(
703    ///     "example.namespace",Params { param1: 50, param2: "panic".to_string() }
704    /// );
705    /// assert!(matches!(handle.get_err().as_ref(), Error::Panic));
706    /// ```
707    pub fn get<K: Cacheable>(
708        &mut self,
709        namespace: impl Into<Namespace>,
710        key: K,
711    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
712        let namespace = namespace.into();
713        self.generate_result(namespace, key, |key| key.generate())
714    }
715
716    /// Gets a handle to a cacheable object from the cache, caching failures as well.
717    ///
718    /// Generates the object in the background if needed.
719    ///
720    /// # Examples
721    ///
722    /// ```
723    /// use cache::{mem::NamespaceCache, error::Error, Cacheable};
724    /// use serde::{Deserialize, Serialize};
725    ///
726    /// #[derive(Deserialize, Serialize, Hash, Eq, PartialEq)]
727    /// pub struct Params {
728    ///     param1: u64,
729    ///     param2: String,
730    /// };
731    ///
732    /// impl Cacheable for Params {
733    ///     type Output = u64;
734    ///     type Error = bool;
735    ///
736    ///     fn generate(&self) -> Result<Self::Output, Self::Error> {
737    ///         if &self.param2 == "panic" {
738    ///             panic!("unrecoverable param");
739    ///         }
740    ///         // Expensive computation...
741    ///         # let computation_result = 5;
742    ///         if computation_result == 5 {
743    ///             return Err(false);
744    ///         }
745    ///         Ok(2 * self.param1)
746    ///     }
747    /// }
748    ///
749    /// let mut cache = NamespaceCache::new();
750    ///
751    /// let handle = cache.get_with_err(
752    ///     "example.namespace", Params { param1: 5, param2: "cache".to_string() }
753    /// );
754    /// assert_eq!(*handle.unwrap_err_inner(), false);
755    ///
756    /// // Does not need to carry out the expensive computation again as the error is cached.
757    /// let handle = cache.get_with_err(
758    ///     "example.namespace", Params { param1: 5, param2: "cache".to_string() }
759    /// );
760    /// assert_eq!(*handle.unwrap_err_inner(), false);
761    /// ```
762    pub fn get_with_err<
763        E: Send + Sync + Serialize + DeserializeOwned + Any,
764        K: Cacheable<Error = E>,
765    >(
766        &mut self,
767        namespace: impl Into<Namespace>,
768        key: K,
769    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
770        let namespace = namespace.into();
771        self.generate(namespace, key, |key| key.generate())
772    }
773
774    /// Gets a handle to a cacheable object from the cache, generating the object in the background
775    /// if needed.
776    ///
777    /// **Note:** The state is not used to determine whether the object should be regenerated. As
778    /// such, it should not impact the output of this function but rather should only be used to
779    /// store collateral or reuse computation from other function calls.
780    ///
781    /// However, the entries generated with different state types are not interchangeable. That is,
782    /// getting the same key with different states will regenerate the key several times, once for
783    /// each state type `S`.
784    ///
785    /// # Examples
786    ///
787    /// ```
788    /// use std::sync::{Arc, Mutex};
789    /// use cache::{mem::NamespaceCache, error::Error, CacheableWithState};
790    /// use serde::{Deserialize, Serialize};
791    ///
792    /// #[derive(Debug, Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
793    /// pub struct Params(u64);
794    ///
795    /// #[derive(Clone)]
796    /// pub struct Log(Arc<Mutex<Vec<Params>>>);
797    ///
798    /// impl CacheableWithState<Log> for Params {
799    ///     type Output = u64;
800    ///     type Error = anyhow::Error;
801    ///
802    ///     fn generate_with_state(&self, state: Log) -> anyhow::Result<u64> {
803    ///         println!("Logging parameters...");
804    ///         state.0.lock().unwrap().push(self.clone());
805    ///
806    ///         if self.0 == 5 {
807    ///             anyhow::bail!("invalid param");
808    ///         } else if self.0 == 8 {
809    ///             panic!("unrecoverable param");
810    ///         }
811    ///
812    ///         Ok(2 * self.0)
813    ///     }
814    /// }
815    ///
816    /// let mut cache = NamespaceCache::new();
817    /// let log = Log(Arc::new(Mutex::new(Vec::new())));
818    ///
819    /// let handle = cache.get_with_state(
820    ///     "example.namespace",
821    ///     Params(0),
822    ///     log.clone(),
823    /// );
824    ///
825    /// assert_eq!(*handle.unwrap_inner(), 0);
826    ///
827    /// let handle = cache.get_with_state(
828    ///     "example.namespace",
829    ///     Params(5),
830    ///     log.clone(),
831    /// );
832    ///
833    /// assert_eq!(format!("{}", handle.unwrap_err_inner().root_cause()), "invalid param");
834    ///
835    /// let handle = cache.get_with_state(
836    ///     "example.namespace",
837    ///     Params(8),
838    ///     log.clone(),
839    /// );
840    ///
841    /// assert!(matches!(handle.get_err().as_ref(), Error::Panic));
842    ///
843    /// assert_eq!(log.0.lock().unwrap().clone(), vec![Params(0), Params(5), Params(8)]);
844    /// ```
845    pub fn get_with_state<S: Send + Sync + Any, K: CacheableWithState<S>>(
846        &mut self,
847        namespace: impl Into<Namespace>,
848        key: K,
849        state: S,
850    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
851        self.generate_result_with_state(namespace, key, state, |key, state| {
852            key.generate_with_state(state)
853        })
854    }
855
856    /// Gets a handle to a cacheable object from the cache, caching failures as well.
857    ///
858    /// Generates the object in the background if needed.
859    ///
860    /// See [`NamespaceCache::get_with_err`] and [`NamespaceCache::get_with_state`] for related examples.
861    pub fn get_with_state_and_err<
862        S: Send + Sync + Any,
863        E: Send + Sync + Serialize + DeserializeOwned + Any,
864        K: CacheableWithState<S, Error = E>,
865    >(
866        &mut self,
867        namespace: impl Into<Namespace>,
868        key: K,
869        state: S,
870    ) -> CacheHandle<std::result::Result<K::Output, K::Error>> {
871        let namespace = namespace.into();
872        self.generate_with_state(namespace, key, state, |key, state| {
873            key.generate_with_state(state)
874        })
875    }
876
877    pub(crate) fn generate_inner<
878        K: Serialize + Any + Send + Sync,
879        V: Serialize + DeserializeOwned + Send + Sync + Any,
880    >(
881        &mut self,
882        namespace: impl Into<Namespace>,
883        key: K,
884        generate_fn: impl GenerateFn<K, V>,
885    ) -> CacheHandleInner<V> {
886        let namespace = namespace.into();
887        self.generate_inner_dispatch(
888            namespace,
889            key,
890            generate_fn,
891            |value| Some(flexbuffers::to_vec(value).unwrap()),
892            |value| flexbuffers::from_slice(value).map_err(|e| Arc::new(e.into())),
893        )
894    }
895    pub(crate) fn generate_result_inner<
896        K: Serialize + Any + Send + Sync,
897        V: Serialize + DeserializeOwned + Send + Sync + Any,
898        E: Send + Sync + Any,
899    >(
900        &mut self,
901        namespace: impl Into<Namespace>,
902        key: K,
903        generate_fn: impl GenerateResultFn<K, V, E>,
904    ) -> CacheHandleInner<std::result::Result<V, E>> {
905        let namespace = namespace.into();
906        self.generate_inner_dispatch(
907            namespace,
908            key,
909            generate_fn,
910            |value| {
911                value
912                    .as_ref()
913                    .ok()
914                    .map(|value| flexbuffers::to_vec(value).unwrap())
915            },
916            |value| {
917                flexbuffers::from_slice(value)
918                    .map(|value| Ok(value))
919                    .map_err(|e| Arc::new(e.into()))
920            },
921        )
922    }
923
924    fn generate_inner_dispatch<K: Serialize + Any + Send + Sync, V: Send + Sync + Any>(
925        &mut self,
926        namespace: Namespace,
927        key: K,
928        generate_fn: impl GenerateFn<K, V>,
929        serialize_value: impl SerializeValueFn<V>,
930        deserialize_value: impl DeserializeValueFn<V>,
931    ) -> CacheHandleInner<V> {
932        let handle = CacheHandleInner::default();
933        let hash = crate::hash(&flexbuffers::to_vec(&key).unwrap());
934
935        let (in_progress, entry) = match self.entries.entry(namespace).or_default().entry(hash) {
936            Entry::Vacant(v) => (false, v.insert(CacheHandleInner::default()).clone()),
937            Entry::Occupied(o) => (true, o.get().clone()),
938        }
939        .clone();
940
941        let entry2 = entry.clone();
942        let handle_clone = handle.clone();
943        thread::spawn(move || {
944            let value = if in_progress {
945                match entry.try_get() {
946                    Ok(Some(value)) => Some(Ok(value)),
947                    Ok(None) => None,
948                    Err(e) => Some(Err(e)),
949                }
950            } else {
951                None
952            };
953            if let Some(value) = value {
954                handle_clone.set(value.and_then(|value| deserialize_value(value)));
955            } else {
956                let v = run_generator(move || generate_fn(&key));
957                if !in_progress {
958                    entry2.set(v.as_ref().map(serialize_value).map_err(|e| e.clone()));
959                }
960                handle_clone.set(v);
961            }
962        });
963
964        handle
965    }
966}