moka-cache 1.1.2

Based on Moka K-V Cache Utils
Documentation
# moka-cache

`moka-cache` 是一个基于 [`moka`](https://crates.io/crates/moka) 的轻量级 K-V 缓存工具库。
它对 `moka::sync::Cache` 做了一层简单封装,提供了:

- 统一的过期时间模型 `Expiration`
- 基于 `serde` + `bincode` 的泛型对象缓存
- 可选的缓存移除/过期回调
- 常用缓存操作,如 `insert``get``remove``refresh`

这个 crate 适合需要在 Rust 项目中快速缓存字符串、数字、字节数组或结构体数据的场景。

## Features

- 基于 `moka::sync::Cache`
- 支持缓存任意实现了 `Serialize` / `DeserializeOwned` 的类型
- 支持多种 TTL:
  - `Never`
  - `Millis(u64)`
  - `Second(u64)`
  - `Minute(u64)`
  - `Hour(u64)`
- 支持通过回调监听缓存项被移除的原因
- 提供手动刷新 TTL 的 `refresh`

## Install

```bash
cargo add moka-cache
```

## Quick Start

```rust
use moka::notification::RemovalCause;
use moka_cache::{Expiration, MokaCache, MokaCacheData};
use std::sync::Arc;

fn on_remove(key: Arc<String>, _value: MokaCacheData, cause: RemovalCause) {
    println!("key={key}, cause={cause:?}");
}

fn main() -> anyhow::Result<()> {
    let cache = MokaCache::new_default(Some(on_remove), 512);

    cache.insert("message", "hello moka", Expiration::Minute(5))?;

    let value = cache.get::<_, String>("message");
    assert_eq!(value, Some((Expiration::Minute(5), "hello moka".to_string())));

    Ok(())
}
```

## Cache Struct Example

```rust
use moka_cache::{Expiration, MokaCache};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct AppConfig {
    path: String,
    cache_capacity: u32,
}

fn main() -> anyhow::Result<()> {
    let cache = MokaCache::new_default(None, 128);

    let config = AppConfig {
        path: "./data".to_string(),
        cache_capacity: 1024,
    };

    cache.insert("app-config", config.clone(), Expiration::Never)?;

    let value = cache.get::<_, AppConfig>("app-config");
    assert_eq!(value, Some((Expiration::Never, config)));

    Ok(())
}
```

## API Overview

### Create Cache

```rust
let cache = MokaCache::new_default(None, 512);
```

- 第一个参数:可选移除回调
- 第二个参数:最大容量 `max_capacity`

### Insert Data

```rust
cache.insert("key", 123_i32, Expiration::Second(30))?;
```

### Read Data

```rust
let value = cache.get::<_, i32>("key");
```

返回值类型:

```rust
Option<(Expiration, V)>
```

其中:

- `Expiration` 是写入时设置的过期策略
- `V` 是反序列化后的实际值

### Remove Data

```rust
cache.remove("key");
```

### Check Existence

```rust
let exists = cache.contains_key("key");
```

### Get Expiration Policy

```rust
let exp = cache.get_exp("key");
```

### Refresh TTL

`refresh` 会按原来的过期策略重新写入当前 key,从而延长生命周期:

```rust
cache.refresh("key")?;
```

如果 key 不存在,会返回错误;如果过期策略是 `Expiration::Never`,则不会执行刷新。

## About Expiration Cleanup

当前库基于 `moka::sync::Cache`,并暴露了:

```rust
cache.check_exp_interval();
```

这个方法内部会调用 `run_pending_tasks()`,适合在后台线程中定期执行,以便更及时地触发过期清理和回调。例如:

```rust
use std::{thread, time::Duration};

thread::spawn({
    let cache = cache_handler.clone();
    move || loop {
        thread::sleep(Duration::from_millis(50));
        cache.check_exp_interval();
    }
});
```

如果你的业务依赖“过期后尽快触发移除回调”,建议显式调度这个方法。

## Supported Value Types

只要类型实现了以下 trait,就可以直接缓存:

- `serde::Serialize`
- `serde::de::DeserializeOwned`

例如:

- `String`
- `bool`
- `i32` / `u32` / `u64`
- `Vec<u8>`
- 自定义结构体

## Public Types

项目当前暴露的核心类型包括:

- `MokaCache`
- `MokaCacheHandler = Arc<MokaCache>`
- `MokaCacheData = (Expiration, Vec<u8>)`
- `Expiration`

## Notes

- key 类型统一使用字符串语义,接口接收 `AsRef<str>`
- value 会以 `bincode` 二进制格式写入缓存
- 读取时如果反序列化失败,会记录错误日志并返回 `None`
- `refresh` 的实现是“读取旧值后重新插入”,适合 TTL 续期场景

## License

MIT