Skip to main content

triblespace_core/blob/
cache.rs

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