use alloy_chains::NamedChain;
use async_trait::async_trait;
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use std::fmt;
use crate::blocks::window::DailyBlockWindow;
use crate::errors::BlockWindowError;
mod disk;
mod memory;
mod noop;
pub mod types;
pub use disk::DiskCache;
pub use memory::MemoryCache;
pub use noop::NoOpCache;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct CacheKey {
pub(crate) chain: NamedChain,
pub(crate) date: NaiveDate,
}
impl CacheKey {
pub fn new(chain: NamedChain, date: NaiveDate) -> Self {
Self { chain, date }
}
}
impl fmt::Display for CacheKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.chain as u64, self.date)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CacheStats {
pub hits: u64,
pub misses: u64,
pub evictions: u64,
pub expirations: u64,
pub entries: usize,
}
impl CacheStats {
pub fn hit_rate(&self) -> f64 {
let total = self.hits + self.misses;
if total == 0 {
0.0
} else {
(self.hits as f64 / total as f64) * 100.0
}
}
}
impl fmt::Display for CacheStats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"hits={}, misses={}, evictions={}, expirations={}, entries={}, hit_rate={:.1}%",
self.hits,
self.misses,
self.evictions,
self.expirations,
self.entries,
self.hit_rate()
)
}
}
#[async_trait]
pub trait BlockWindowCache: Send + Sync {
async fn get(&self, key: &CacheKey) -> Option<DailyBlockWindow>;
async fn insert(&self, key: CacheKey, window: DailyBlockWindow)
-> Result<(), BlockWindowError>;
async fn clear(&self) -> Result<(), BlockWindowError>;
async fn stats(&self) -> CacheStats;
fn name(&self) -> &'static str;
}