use std::sync::Arc;
use std::time::Duration;
use tokio_util::sync::CancellationToken;
use crate::proxy::cache::CacheStore;
use crate::proxy::metrics::ProxyMetrics;
#[derive(Debug, Clone)]
pub struct CleanupConfig {
pub interval: Duration,
pub check_integrity: bool,
}
impl Default for CleanupConfig {
fn default() -> Self {
Self {
interval: Duration::from_secs(300), check_integrity: false,
}
}
}
pub struct CleanupWorker {
cache: Arc<CacheStore>,
metrics: Option<Arc<ProxyMetrics>>,
config: CleanupConfig,
cancel: CancellationToken,
}
impl CleanupWorker {
pub fn new(cache: Arc<CacheStore>, config: CleanupConfig, cancel: CancellationToken) -> Self {
Self {
cache,
metrics: None,
config,
cancel,
}
}
pub fn with_metrics(
cache: Arc<CacheStore>,
metrics: Arc<ProxyMetrics>,
config: CleanupConfig,
cancel: CancellationToken,
) -> Self {
Self {
cache,
metrics: Some(metrics),
config,
cancel,
}
}
pub async fn run(&self) {
let mut interval = tokio::time::interval(self.config.interval);
interval.tick().await;
loop {
tokio::select! {
_ = self.cancel.cancelled() => {
break;
}
_ = interval.tick() => {
self.cleanup().await;
}
}
}
}
async fn cleanup(&self) {
let evicted = self.cache.evict_truly_expired();
if evicted > 0 {
if let Some(ref m) = self.metrics {
for _ in 0..evicted {
m.record_eviction();
}
}
}
if self.config.check_integrity {
let report = self.cache.verify_integrity();
if report.invalid > 0 {
if let Some(ref m) = self.metrics {
for _ in 0..report.invalid {
m.record_integrity_failure();
}
}
}
}
}
}
#[cfg(test)]
#[path = "tests/cleanup_tests.rs"]
mod tests;