use std::sync::{Arc, Mutex};
use arc_swap::{ArcSwap, ArcSwapAny};
use crate::api::{BackendSlot, CacheServiceOptions};
use crate::cacheservice::CacheNamespaceConf;
#[derive(Debug, thiserror::Error)]
pub(crate) enum NamespaceApplyError {
#[error("memcache backend build error: {0}")]
Build(#[from] crate::Error),
}
pub(crate) struct CacheServiceInner {
update_gate: Mutex<()>,
options: CacheServiceOptions,
backend: Arc<ArcSwapAny<Arc<BackendSlot>>>,
applied: ArcSwap<CacheNamespaceConf>,
}
impl std::fmt::Debug for CacheServiceInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CacheServiceInner").finish_non_exhaustive()
}
}
impl CacheServiceInner {
pub(crate) fn new(
initial: CacheNamespaceConf,
backend: Arc<ArcSwapAny<Arc<BackendSlot>>>,
options: CacheServiceOptions,
) -> Arc<Self> {
Arc::new(Self {
update_gate: Mutex::new(()),
options,
backend,
applied: ArcSwap::from_pointee(initial),
})
}
pub fn apply(&self, next: CacheNamespaceConf) -> Result<(), NamespaceApplyError> {
let _update = self.update_gate.lock().expect("update gate poisoned");
if **self.applied.load() == next {
return Ok(());
}
let current = self.backend.load_full();
let backend = crate::CacheService::build_backend(&next, &self.options, current.topology())?;
self.backend.store(Arc::new(backend));
self.applied.store(Arc::new(next));
Ok(())
}
}