mod common;
use common::*;
use multi_tier_cache::CacheStrategy;
use std::time::Duration;
use tokio::time::sleep;
#[tokio::test]
async fn test_invalidate_single_key() {
let cache = setup_cache_with_invalidation()
.await
.unwrap_or_else(|_| panic!("Failed to setup cache"));
let key = test_key("invalidate");
let value = test_data::bytes_user(1);
cache
.set_with_strategy(&key, value.clone(), CacheStrategy::MediumTerm)
.await
.unwrap_or_else(|_| panic!("Failed to set cache"));
let cached = cache
.get(&key)
.await
.unwrap_or_else(|_| panic!("Failed to get cache"));
assert_eq!(cached, Some(value));
cache
.invalidate(&key)
.await
.unwrap_or_else(|_| panic!("Failed to invalidate"));
let cached2 = cache
.get(&key)
.await
.unwrap_or_else(|_| panic!("Failed to get cache"));
assert_eq!(cached2, None);
}
#[tokio::test]
async fn test_update_cache() {
let cache = setup_cache_with_invalidation()
.await
.unwrap_or_else(|_| panic!("Failed to setup cache"));
let key = test_key("update");
let value1 = test_data::bytes_user(1);
let value2 = test_data::bytes_user(2);
cache
.set_with_strategy(&key, value1.clone(), CacheStrategy::MediumTerm)
.await
.unwrap_or_else(|_| panic!("Failed to set cache"));
cache
.update_cache(&key, value2.clone(), Some(Duration::from_secs(300)))
.await
.unwrap_or_else(|_| panic!("Failed to update cache"));
sleep(Duration::from_millis(500)).await;
let cached = cache
.get(&key)
.await
.unwrap_or_else(|_| panic!("Failed to get cache"));
assert_eq!(cached, Some(value2));
}
#[tokio::test]
async fn test_invalidate_pattern() {
common::init_test_tracing();
let cache = setup_cache_with_invalidation()
.await
.unwrap_or_else(|_| panic!("Failed to setup cache"));
let prefix = format!("user:pattern:{}:", rand::random::<u32>());
for i in 1..=5 {
let key = format!("{prefix}key{i}");
let value = test_data::bytes_user(i);
cache
.set_with_strategy(&key, value, CacheStrategy::MediumTerm)
.await
.unwrap_or_else(|_| panic!("Failed to set cache"));
}
let pattern = format!("{prefix}*");
cache
.invalidate_pattern(&pattern)
.await
.unwrap_or_else(|_| panic!("Failed to invalidate pattern"));
let mut all_invalidated = false;
for _ in 0..10 {
let mut still_present = 0;
for i in 1..=5 {
let key = format!("{prefix}key{i}");
if cache.get(&key).await.unwrap_or(None).is_some() {
still_present += 1;
}
}
if still_present == 0 {
all_invalidated = true;
break;
}
sleep(Duration::from_millis(100)).await;
}
assert!(
all_invalidated,
"All keys matching pattern should be eventually invalidated"
);
}
#[tokio::test]
async fn test_set_with_broadcast() {
let cache = setup_cache_with_invalidation()
.await
.unwrap_or_else(|_| panic!("Failed to setup cache"));
let key = test_key("broadcast");
let value = test_data::bytes_user(3);
cache
.set_with_broadcast(&key, value.clone(), CacheStrategy::ShortTerm)
.await
.unwrap_or_else(|_| panic!("Failed to set cache"));
sleep(Duration::from_millis(500)).await;
let cached = cache
.get(&key)
.await
.unwrap_or_else(|_| panic!("Failed to get cache"));
assert_eq!(cached, Some(value));
}
#[tokio::test]
async fn test_invalidation_stats() {
let cache = setup_cache_with_invalidation()
.await
.unwrap_or_else(|_| panic!("Failed to setup cache"));
let key = test_key("stats");
let value = test_data::bytes_user(4);
cache
.set_with_strategy(&key, value.clone(), CacheStrategy::ShortTerm)
.await
.unwrap_or_else(|_| panic!("Failed to set cache"));
cache
.invalidate(&key)
.await
.unwrap_or_else(|_| panic!("Failed to invalidate"));
if let Some(stats) = cache.invalidation_stats() {
assert!(
stats.messages_sent >= 1,
"Should have sent invalidation messages"
);
} else {
panic!("Invalidation stats should be available");
}
}
#[tokio::test]
async fn test_bulk_invalidation() {
let cache = setup_cache_with_invalidation()
.await
.unwrap_or_else(|_| panic!("Failed to setup cache"));
let keys: Vec<String> = (1..=10).map(|i| test_key(&format!("bulk{i}"))).collect();
for (i, key) in keys.iter().enumerate() {
let value = test_data::bytes_user((i + 1) as u64);
cache
.set_with_strategy(key, value, CacheStrategy::ShortTerm)
.await
.unwrap_or_else(|_| panic!("Failed to set cache"));
}
for key in &keys {
cache
.invalidate(key)
.await
.unwrap_or_else(|_| panic!("Failed to invalidate"));
}
sleep(Duration::from_millis(500)).await;
for key in &keys {
let cached = cache
.get(key)
.await
.unwrap_or_else(|_| panic!("Failed to get cache"));
assert_eq!(cached, None);
}
}