use std::hash::Hash;
use std::marker::PhantomData;
use tick::Clock;
use super::buildable::Buildable;
use super::sealed::{CacheTierBuilder, Sealed};
use crate::Cache;
use crate::refresh::TimeToRefresh;
use crate::telemetry::CacheTelemetry;
#[derive(Debug)]
#[expect(clippy::struct_field_names, reason = "builder field naming is intentional")]
pub struct FallbackBuilder<K, V, PB, FB> {
pub(crate) name: Option<&'static str>,
pub(crate) primary_builder: PB,
pub(crate) fallback_builder: FB,
pub(crate) clock: Clock,
pub(crate) refresh: Option<TimeToRefresh<K>>,
pub(crate) telemetry: CacheTelemetry,
pub(crate) stampede_protection: bool,
pub(crate) _phantom: PhantomData<(K, V)>,
}
impl<K, V, PB, FB> FallbackBuilder<K, V, PB, FB> {
#[must_use]
pub fn time_to_refresh(mut self, refresh: TimeToRefresh<K>) -> Self {
self.refresh = Some(refresh);
self
}
#[must_use]
pub fn stampede_protection(mut self) -> Self {
self.stampede_protection = true;
self
}
}
impl<K, V, PB, FB> FallbackBuilder<K, V, PB, FB>
where
K: Clone + Hash + Eq + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
{
pub fn fallback<FB2>(self, fallback: FB2) -> FallbackBuilder<K, V, Self, FB2>
where
FB2: CacheTierBuilder<K, V>,
{
let clock = self.clock.clone();
let telemetry = self.telemetry.clone();
let stampede_protection = self.stampede_protection;
FallbackBuilder {
name: self.name,
primary_builder: self,
fallback_builder: fallback,
clock,
refresh: None,
telemetry,
stampede_protection,
_phantom: PhantomData,
}
}
}
impl<K, V, PB, FB> Sealed for FallbackBuilder<K, V, PB, FB>
where
PB: CacheTierBuilder<K, V>,
FB: CacheTierBuilder<K, V>,
{
}
impl<K, V, PB, FB> CacheTierBuilder<K, V> for FallbackBuilder<K, V, PB, FB>
where
K: Clone + Hash + Eq + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
PB: CacheTierBuilder<K, V>,
FB: CacheTierBuilder<K, V>,
{
}
#[expect(private_bounds, reason = "Buildable is an internal trait")]
impl<K, V, PB, FB> FallbackBuilder<K, V, PB, FB>
where
K: Clone + Eq + Hash + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
PB: CacheTierBuilder<K, V> + Buildable<K, V>,
FB: CacheTierBuilder<K, V> + Buildable<K, V>,
{
pub fn build(self) -> Cache<K, V> {
<Self as Buildable<K, V>>::build(self)
}
}