pub mod block_source;
pub mod config;
pub mod disk;
pub mod in_memory;
use std::sync::Arc;
use bytes::Bytes;
pub use config::{CacheEvictionPolicy, ColdFetchMode, DiskCacheConfig, LruPolicy};
pub use disk::{CacheStats, DiskCacheError, DiskCacheStore};
pub use in_memory::InMemoryReaderCache;
use thiserror::Error;
use super::manifest::SuperfileUri;
use crate::superfile::{ReadError, SuperfileReader};
pub trait SuperfileReaderCache: Send + Sync {
fn reader(&self, uri: &SuperfileUri) -> Result<Arc<SuperfileReader>, ReaderCacheError>;
fn insert(&self, uri: SuperfileUri, bytes: Bytes) -> Result<(), ReaderCacheError>;
fn resident_bytes(&self) -> usize;
fn remove(&self, _uri: &SuperfileUri) {}
}
#[derive(Debug, Error)]
pub enum ReaderCacheError {
#[error("superfile uri {uri:?} not found in cache")]
NotFound { uri: SuperfileUri },
#[error("failed to open superfile bytes: {source}")]
OpenFailed {
#[source]
source: ReadError,
},
}
#[cfg(test)]
mod trait_default_tests {
use super::*;
struct IgnoresRemoval;
impl SuperfileReaderCache for IgnoresRemoval {
fn reader(&self, uri: &SuperfileUri) -> Result<Arc<SuperfileReader>, ReaderCacheError> {
Err(ReaderCacheError::NotFound { uri: *uri })
}
fn insert(&self, _uri: SuperfileUri, _bytes: Bytes) -> Result<(), ReaderCacheError> {
Ok(())
}
fn resident_bytes(&self) -> usize {
0
}
}
#[test]
fn default_remove_is_a_safe_no_op() {
let cache = IgnoresRemoval;
let uri = SuperfileUri::new_v4();
cache.remove(&uri);
assert!(
matches!(cache.reader(&uri), Err(ReaderCacheError::NotFound { .. })),
"remove neither panics nor changes the miss contract"
);
assert_eq!(cache.resident_bytes(), 0);
}
}