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