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;