#![cfg(feature = "redis")]
use cacheflight::{CacheFlight, LookupState, RedisCache, Result};
use redis::aio::ConnectionManager;
use std::time::Duration;
fn redis_conn() -> ConnectionManager {
use testcontainers::GenericImage;
use testcontainers::clients::Cli;
let client: &'static Cli = Box::leak(Box::new(Cli::default()));
let image = GenericImage::new("redis", "7-alpine").with_exposed_port(6379);
let container = client.run(image);
let port = container.get_host_port_ipv4(6379);
std::mem::forget(container);
let url = format!("redis://127.0.0.1:{port}/");
let client = redis::Client::open(url).expect("invalid redis url");
tokio::runtime::Runtime::new()
.expect("tokio runtime")
.block_on(ConnectionManager::new(client))
.expect("connection manager")
}
#[ignore]
#[tokio::test]
async fn redis_cache_basic_dedup() -> Result<()> {
let conn = redis_conn();
let cache = RedisCache::new(conn);
let cf = CacheFlight::new(cache).ttl(Duration::from_secs(30));
let result = cf
.run("dedup-key", || async { Ok(b"redis-value".to_vec()) })
.await?;
assert_eq!(result.state(), LookupState::Recomputed);
assert_eq!(result.value(), b"redis-value");
let cached = cf
.run("dedup-key", || async {
unreachable!("should read from cache")
})
.await?;
assert_eq!(cached.state(), LookupState::CacheHit);
assert_eq!(cached.value(), b"redis-value");
Ok(())
}
#[ignore]
#[tokio::test]
async fn redis_cache_with_swr() -> Result<()> {
let conn = redis_conn();
let cache = RedisCache::new(conn);
let cf = CacheFlight::new(cache)
.stale_while_revalidate(Duration::from_millis(100), Duration::from_secs(10));
cf.run("swr-key", || async {
tokio::time::sleep(Duration::from_millis(20)).await;
Ok(b"swr-value".to_vec())
})
.await?;
tokio::time::sleep(Duration::from_millis(150)).await;
let stale = cf
.run("swr-key", || async {
unreachable!("background refresh should serve this")
})
.await?;
assert_eq!(stale.state(), LookupState::Stale);
assert_eq!(stale.value(), b"swr-value");
Ok(())
}