fache 0.1.308

发车工具箱
Documentation
use std::collections::HashMap;
use tokio::sync::RwLock;

use std::hash::Hash;
use std::time::{Duration, Instant};

#[derive(Clone, Debug)]
pub struct Item<T> {
    pub object: T,           // 存储的实际值
    expiry: Option<Instant>, // 可选的过期时间
}

impl<T> Item<T> {
    /// 创建新缓存项
    pub fn new(object: T, item_duration: Option<Duration>) -> Self {
        let expiry = item_duration.map(|duration| Instant::now() + duration);
        Item { object, expiry }
    }

    /// 检查是否过期
    pub fn expired(&self) -> bool {
        self.expiry
            .map(|expiry| expiry < Instant::now())
            .unwrap_or(false)
    }
}

#[derive(Debug)]
pub struct Cache<T, V> {
    items: RwLock<HashMap<T, Item<V>>>, // 线程安全的哈希映射
}

impl<T, V> Cache<T, V> {
    pub fn new() -> Self {
        Cache {
            items: RwLock::new(HashMap::new()),
        }
    }

    /// 获取与给定键关联的缓存项
    pub async fn get(&self, key: &T) -> Option<V>
    where
        T: Eq + Hash,
        V: Clone,
    {
        self.items
            .read() // 获取读锁
            .await
            .get(key) // 查找键
            .filter(|item| !item.expired()) // 过滤未过期的
            .map(|item| item.object.clone()) // 克隆值
    }
    /// 使用关联的键设置缓存中的一项(带过期时间,单位:秒)
    pub async fn set_with_seconds(&self, key: T, value: V, seconds: u64) -> Option<V>
    where
        T: Eq + Hash,
    {
        self.set(key, value, Some(Duration::from_secs(seconds)))
            .await
    }
    /// 使用关联的键设置缓存中的一项
    pub async fn set(&self, key: T, value: V, custom_duration: Option<Duration>) -> Option<V>
    where
        T: Eq + Hash,
    {
        self.items
            .write() // 获取写锁
            .await
            .insert(key, Item::new(value, custom_duration)) // 插入新项
            .map(|item| item.object) // 返回旧值(如果有)
    }
    /// 从缓存中移除所有已过期的项
    pub async fn remove_expired(&self)
    where
        T: Eq + Hash + Clone,
    {
        // 1. 获取所有过期键
        let expired_keys = self
            .items
            .read()
            .await
            .iter()
            .filter(|(_, item)| item.expired())
            .map(|(k, _)| k.clone())
            .collect::<Vec<T>>();
        // 2. 移除这些键对应的项
        for key in expired_keys {
            self.items.write().await.remove(&key);
        }
    }

    /// 从缓存中移除指定项
    pub async fn remove(&self, key: &T) -> Option<V>
    where
        T: Eq + Hash,
    {
        self.items.write().await.remove(key).map(|item| item.object)
    }

    /// 清除缓存中的所有项,不考虑过期时间
    pub async fn clear(&self) {
        self.items.write().await.clear()
    }
}