Skip to main content

feldera_buffer_cache/
lib.rs

1//! Weighted in-memory buffer caches with LRU and S3-FIFO eviction.
2
3mod builder;
4mod lru;
5mod s3_fifo;
6mod thread_type;
7
8use std::any::Any;
9use std::sync::Arc;
10
11pub use builder::BufferCacheBuilder;
12use feldera_types::config::dev_tweaks::BufferCacheStrategy;
13pub use lru::LruCache;
14pub use s3_fifo::S3FifoCache;
15pub use thread_type::ThreadType;
16
17/// Cached values expose their memory cost directly to the cache backends.
18pub trait CacheEntry: Any + Send + Sync {
19    /// Returns the cost of this value in bytes.
20    fn cost(&self) -> usize;
21}
22
23impl<T> CacheEntry for Arc<T>
24where
25    T: CacheEntry + ?Sized + 'static,
26{
27    fn cost(&self) -> usize {
28        (**self).cost()
29    }
30}
31
32impl dyn CacheEntry {
33    /// Attempts to downcast an `Arc<dyn CacheEntry>` to a concrete entry type.
34    pub fn downcast<T>(self: Arc<Self>) -> Option<Arc<T>>
35    where
36        T: Send + Sync + 'static,
37    {
38        (self as Arc<dyn Any + Send + Sync>).downcast().ok()
39    }
40}
41
42/// Shared trait object used to pass buffer-cache backends around.
43pub type SharedBufferCache<K, V> = Arc<dyn BufferCache<K, V>>;
44
45/// Common object-safe API implemented by all buffer-cache backends.
46pub trait BufferCache<K, V>: Any + Send + Sync {
47    /// Returns this backend as [`Any`] for backend-specific downcasts.
48    fn as_any(&self) -> &dyn Any;
49
50    /// Returns the eviction strategy used by this cache.
51    fn strategy(&self) -> BufferCacheStrategy;
52
53    /// Inserts or replaces `key` with `value`.
54    ///
55    /// When a key, value is inserted with a the cost that exceeds
56    /// the capacity of a shard in the cache, it is up to the
57    /// implementation to decided if it wants to store/accept
58    /// the key, value pair.
59    fn insert(&self, key: K, value: V);
60
61    /// Looks up `key` and returns a clone of the stored value.
62    fn get(&self, key: K) -> Option<V>;
63
64    /// Removes `key` if it is present and returns the removed value.
65    fn remove(&self, key: &K) -> Option<V>;
66
67    /// Removes every entry whose key matches `predicate`.
68    fn remove_if(&self, predicate: &dyn Fn(&K) -> bool);
69
70    /// Returns `true` if `key` is currently resident.
71    fn contains_key(&self, key: &K) -> bool;
72
73    /// Returns the number of resident entries.
74    fn len(&self) -> usize;
75
76    /// Returns `true` if the cache has no resident entries.
77    fn is_empty(&self) -> bool {
78        self.len() == 0
79    }
80
81    /// Returns the total resident weight.
82    fn total_charge(&self) -> usize;
83
84    /// Returns the configured total weight capacity.
85    fn total_capacity(&self) -> usize;
86
87    /// Returns the number of shards used by this backend.
88    fn shard_count(&self) -> usize;
89
90    /// Returns `(used_charge, capacity)` for shard `idx`.
91    #[cfg(test)]
92    fn shard_usage(&self, idx: usize) -> (usize, usize);
93}
94
95#[cfg(test)]
96mod tests;