use axum::http::HeaderMap;
use brk_types::{BlockHashPrefix, Version};
use crate::{VERSION, extended::HeaderMapExtended};
pub enum CacheStrategy {
Tip,
Immutable(Version),
Static,
BlockBound(Version, BlockHashPrefix),
MempoolHash(u64),
}
pub(crate) const CACHE_CONTROL: &str = "public, max-age=1, must-revalidate";
pub struct CacheParams {
pub etag: Option<String>,
pub cache_control: &'static str,
}
impl CacheParams {
pub fn tip(tip: BlockHashPrefix) -> Self {
Self {
etag: Some(format!("t{:x}", *tip)),
cache_control: CACHE_CONTROL,
}
}
pub fn immutable(version: Version) -> Self {
Self {
etag: Some(format!("i{version}")),
cache_control: CACHE_CONTROL,
}
}
pub fn block_bound(version: Version, prefix: BlockHashPrefix) -> Self {
Self {
etag: Some(format!("b{version}-{:x}", *prefix)),
cache_control: CACHE_CONTROL,
}
}
pub fn static_version() -> Self {
Self {
etag: Some(format!("s{VERSION}")),
cache_control: CACHE_CONTROL,
}
}
pub fn mempool_hash(hash: u64) -> Self {
Self {
etag: Some(format!("m{hash:x}")),
cache_control: CACHE_CONTROL,
}
}
pub fn etag_str(&self) -> &str {
self.etag.as_deref().unwrap_or("")
}
pub fn matches_etag(&self, headers: &HeaderMap) -> bool {
self.etag
.as_ref()
.is_some_and(|etag| headers.has_etag(etag))
}
pub fn resolve(strategy: &CacheStrategy, tip: impl FnOnce() -> BlockHashPrefix) -> Self {
match strategy {
CacheStrategy::Tip => Self::tip(tip()),
CacheStrategy::Immutable(v) => Self::immutable(*v),
CacheStrategy::BlockBound(v, prefix) => Self::block_bound(*v, *prefix),
CacheStrategy::Static => Self::static_version(),
CacheStrategy::MempoolHash(hash) => Self::mempool_hash(*hash),
}
}
}