use crate::{ColdReceipt, Confirmed};
use alloy::primitives::BlockNumber;
use lru::LruCache;
use signet_storage_types::{RecoveredTx, SealedHeader};
use std::num::NonZeroUsize;
const DEFAULT_CACHE_CAPACITY: usize = 2048;
fn evict_where<K: Copy + Eq + std::hash::Hash, V>(
cache: &mut LruCache<K, V>,
predicate: impl Fn(&K) -> bool,
) {
let keys: Vec<_> = cache.iter().filter(|(k, _)| predicate(k)).map(|(k, _)| *k).collect();
keys.into_iter().for_each(|k| {
cache.pop(&k);
});
}
pub(crate) struct ColdCache {
transactions: LruCache<(BlockNumber, u64), Confirmed<RecoveredTx>>,
receipts: LruCache<(BlockNumber, u64), ColdReceipt>,
headers: LruCache<BlockNumber, SealedHeader>,
}
impl ColdCache {
pub(crate) fn new() -> Self {
Self::new_with_cap(DEFAULT_CACHE_CAPACITY)
}
pub(crate) fn new_with_cap(cap: usize) -> Self {
let cap = NonZeroUsize::new(cap).expect("cache capacity must be non-zero");
Self {
transactions: LruCache::new(cap),
receipts: LruCache::new(cap),
headers: LruCache::new(cap),
}
}
pub(crate) fn get_tx(&mut self, key: &(BlockNumber, u64)) -> Option<Confirmed<RecoveredTx>> {
self.transactions.get(key).cloned()
}
pub(crate) fn put_tx(&mut self, key: (BlockNumber, u64), val: Confirmed<RecoveredTx>) {
self.transactions.put(key, val);
}
pub(crate) fn get_receipt(&mut self, key: &(BlockNumber, u64)) -> Option<ColdReceipt> {
self.receipts.get(key).cloned()
}
pub(crate) fn put_receipt(&mut self, key: (BlockNumber, u64), val: ColdReceipt) {
self.receipts.put(key, val);
}
pub(crate) fn get_header(&mut self, block: &BlockNumber) -> Option<SealedHeader> {
self.headers.get(block).cloned()
}
pub(crate) fn put_header(&mut self, block: BlockNumber, header: SealedHeader) {
self.headers.put(block, header);
}
pub(crate) fn invalidate_above(&mut self, block: u64) {
evict_where(&mut self.transactions, |(bn, _)| *bn > block);
evict_where(&mut self.receipts, |(bn, _)| *bn > block);
evict_where(&mut self.headers, |bn| *bn > block);
}
}