Skip to main content

triblespace_core/blob/
cache.rs

1use std::sync::Arc;
2
3use quick_cache::sync::Cache;
4
5use crate::blob::BlobSchema;
6use crate::blob::TryFromBlob;
7use crate::repo::BlobStoreGet;
8use crate::value::schemas::hash::Handle;
9use crate::value::schemas::hash::HashProtocol;
10use crate::value::Value;
11use crate::value::ValueSchema;
12
13const DEFAULT_BLOB_CACHE_CAPACITY: usize = 256;
14
15/// Lazy cache for blob conversions keyed by blob handle.
16pub struct BlobCache<B, H, S, T>
17where
18    B: BlobStoreGet<H>,
19    H: HashProtocol,
20    S: BlobSchema + 'static,
21    T: TryFromBlob<S>,
22    Handle<H, S>: ValueSchema,
23{
24    blobs: B,
25    by_handle: Cache<Value<Handle<H, S>>, Arc<T>>,
26}
27
28impl<B, H, S, T> BlobCache<B, H, S, T>
29where
30    B: BlobStoreGet<H>,
31    H: HashProtocol,
32    S: BlobSchema + 'static,
33    T: TryFromBlob<S>,
34    Handle<H, S>: ValueSchema,
35{
36    /// Creates a new cache backed by `blobs` with the default capacity.
37    pub fn new(blobs: B) -> Self {
38        Self::with_capacity(blobs, DEFAULT_BLOB_CACHE_CAPACITY)
39    }
40
41    /// Creates a new cache backed by `blobs` with the given entry capacity.
42    pub fn with_capacity(blobs: B, capacity: usize) -> Self {
43        Self {
44            blobs,
45            by_handle: Cache::new(capacity),
46        }
47    }
48
49    /// Returns the cached value for `handle`, fetching and converting it on a cache miss.
50    pub fn get(&self, handle: Value<Handle<H, S>>) -> Result<Arc<T>, B::GetError<T::Error>> {
51        let blobs = &self.blobs;
52        self.by_handle.get_or_insert_with(&handle, || {
53            let value = blobs.get::<T, S>(handle)?;
54            Ok(Arc::new(value))
55        })
56    }
57}