autocache 0.4.0

automatic cache management
Documentation
use futures::FutureExt;
use serde::{Deserialize, Serialize};

use crate::{redis_cache::RedisCache, AutoCache, Cache, Codec, Entry};

#[derive(Serialize, Deserialize, Debug, Clone)]
struct Item {
    count: u32,
    message: String,
}

impl Codec for Item {}

#[derive(Serialize, Deserialize, Debug, Clone)]
struct FailingEncodeItem;

impl Codec for FailingEncodeItem {
    fn encode(&self) -> anyhow::Result<bytes::Bytes> {
        anyhow::bail!("encode failed")
    }
}

#[tokio::test]
async fn test_mset_propagates_encode_errors() {
    let redis_cli = redis::Client::open("redis://127.0.0.1:1/").unwrap();
    let cache: RedisCache<String, Entry<String, FailingEncodeItem>> = RedisCache::new(redis_cli);
    let entry = Entry {
        key: "test-key".to_string(),
        value: Some(FailingEncodeItem),
        expire_at_ms: None,
    };

    let error = cache
        .mset(&[("test-key".to_string(), entry)])
        .await
        .err()
        .unwrap();

    assert_eq!(error.to_string(), "encode failed");
}

#[tokio::test]
#[ignore = "requires a Redis server"]
async fn test_redis_cache() {
    let _ = tracing_subscriber::fmt::try_init();

    let redis_url =
        std::env::var("AUTOCACHE_REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1/".to_string());
    let redis_cli = redis::Client::open(redis_url).unwrap();

    let ac = AutoCache::builder()
        .cache(RedisCache::new(redis_cli))
        .expire_time(std::time::Duration::from_secs(10))
        .use_expired_data(true)
        .single_loader(|key: String, ()| {
            async move {
                Ok(Some(Item {
                    count: 1,
                    message: key.clone(),
                }))
            }
            .boxed()
        })
        .build()
        .unwrap();

    let key = "autocache:test:redis-cache".to_string();
    ac.mdel(std::slice::from_ref(&key)).await.unwrap();

    let values = ac.mget(&[(key.clone(), ())]).await.unwrap();

    assert_eq!(values.len(), 1);
    assert_eq!(values[0].0, key);
    assert_eq!(values[0].1.message, "autocache:test:redis-cache");

    ac.mdel(std::slice::from_ref(&key)).await.unwrap();
}