oxcache 0.1.2

A high-performance, production-ready Rust multi-level cache library providing L1 (Moka) and L2 (Redis) caching.
Documentation
<div align="center">

# ๐Ÿš€ Oxcache

[![CI](https://github.com/Kirky-X/oxcache/actions/workflows/ci.yml/badge.svg)](https://github.com/Kirky-X/oxcache/actions/workflows/ci.yml)
[![Crates.io](https://img.shields.io/crates/v/oxcache.svg)](https://crates.io/crates/oxcache)
[![Documentation](https://docs.rs/oxcache/badge.svg)](https://docs.rs/oxcache)
[![Downloads](https://img.shields.io/crates/d/oxcache.svg)](https://crates.io/crates/oxcache)
[![codecov](https://codecov.io/gh/Kirky-X/oxcache/branch/main/graph/badge.svg)](https://codecov.io/gh/Kirky-X/oxcache)
[![Dependency Status](https://deps.rs/repo/github/Kirky-X/oxcache/status.svg)](https://deps.rs/repo/github/Kirky-X/oxcache)
[![License](https://img.shields.io/crates/l/oxcache.svg)](https://github.com/Kirky-X/oxcache/blob/main/LICENSE)
[![Rust Version](https://img.shields.io/badge/rust-1.70%2B-blue.svg)](https://www.rust-lang.org)

[English]../README.md | ็ฎ€ไฝ“ไธญๆ–‡

้ซ˜ๆ€ง่ƒฝใ€็”Ÿไบง็บง็š„ Rust ๅŒๅฑ‚็ผ“ๅญ˜ๅบ“๏ผŒๆไพ› L1๏ผˆMoka ๅ†…ๅญ˜็ผ“ๅญ˜๏ผ‰+ L2๏ผˆRedis ๅˆ†ๅธƒๅผ็ผ“ๅญ˜๏ผ‰ๅŒๅฑ‚ๆžถๆž„ใ€‚

</div>

## โœจ ๆ ธๅฟƒ็‰นๆ€ง

<div align="center">

<table>
<tr>
<td width="20%" align="center">
<img src="https://img.icons8.com/fluency/96/000000/rocket.png" width="48"><br>
<b>ๆž่‡ดๆ€ง่ƒฝ</b><br>L1 ็บณ็ง’็บงๅ“ๅบ”
</td>
<td width="20%" align="center">
<img src="https://img.icons8.com/fluency/96/000000/magic-wand.png" width="48"><br>
<b>้›ถไพตๅ…ฅๅผ</b><br>ไธ€่กŒไปฃ็ ๅฏ็”จ็ผ“ๅญ˜
</td>
<td width="20%" align="center">
<img src="https://img.icons8.com/fluency/96/000000/cloud.png" width="48"><br>
<b>่‡ชๅŠจๆ•…้šœๆขๅค</b><br>Redis ๆ•…้šœ่‡ชๅŠจ้™็บง
</td>
<td width="20%" align="center">
<img src="https://img.icons8.com/fluency/96/000000/synchronize.png" width="48"><br>
<b>ๅคšๅฎžไพ‹ๅŒๆญฅ</b><br>ๅŸบไบŽ Pub/Sub ๆœบๅˆถ
</td>
<td width="20%" align="center">
<img src="https://img.icons8.com/fluency/96/000000/lightning.png" width="48"><br>
<b>ๆ‰น้‡ไผ˜ๅŒ–</b><br>ๆ™บ่ƒฝๆ‰น้‡ๅ†™ๅ…ฅ
</td>
</tr>
</table>

</div>

- **๐Ÿš€ ๆž่‡ดๆ€ง่ƒฝ**: L1 ็บณ็ง’็บงๅ“ๅบ”๏ผˆP99 < 100ns๏ผ‰๏ผŒL2 ๆฏซ็ง’็บงๅ“ๅบ”๏ผˆP99 < 5ms๏ผ‰
- **๐ŸŽฏ ้›ถไพตๅ…ฅๅผ**: ้€š่ฟ‡ `#[cached]` ๅฎไธ€่กŒไปฃ็ ๅฏ็”จ็ผ“ๅญ˜
- **๐Ÿ”„ ่‡ชๅŠจๆ•…้šœๆขๅค**: Redis ๆ•…้šœๆ—ถ่‡ชๅŠจ้™็บง๏ผŒๆขๅคๅŽ่‡ชๅŠจ้‡ๆ”พ WAL
- **๐ŸŒ ๅคšๅฎžไพ‹ๅŒๆญฅ**: ๅŸบไบŽ Pub/Sub + ็‰ˆๆœฌๅท็š„ๅคฑๆ•ˆๅŒๆญฅๆœบๅˆถ
- **โšก ๆ‰น้‡ไผ˜ๅŒ–**: ๆ™บ่ƒฝๆ‰น้‡ๅ†™ๅ…ฅ๏ผŒๅคงๅน…ๆๅ‡ๅžๅ้‡
- **๐Ÿ›ก๏ธ ็”Ÿไบง็บงๅฏ้ **: ๅฎŒๆ•ด็š„ๅฏ่ง‚ๆต‹ๆ€งใ€ๅฅๅบทๆฃ€ๆŸฅใ€ๆททๆฒŒๆต‹่ฏ•้ชŒ่ฏ

## ๐Ÿ“ฆ ๅฟซ้€Ÿๅผ€ๅง‹

### ๅฎ‰่ฃ…

ๅœจ `Cargo.toml` ไธญๆทปๅŠ ไพ่ต–๏ผš

```toml
[dependencies]
oxcache = "0.1"
```

> **ๆณจๆ„**๏ผš`tokio` ๅ’Œ `serde` ๅทฒ้ป˜่ฎคๅŒ…ๅซใ€‚ๅฆ‚ๆžœ้œ€่ฆๆœ€ๅฐไพ่ต–๏ผŒๅฏไปฅไฝฟ็”จ
`oxcache = { version = "0.1", default-features = false }` ๆ‰‹ๅŠจๆทปๅŠ ใ€‚

### ๆœ€็ฎ€็คบไพ‹

```rust
use oxcache::macros::cached;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug)]
struct User {
    id: u64,
    name: String,
}

// ไธ€่กŒไปฃ็ ๅฏ็”จ็ผ“ๅญ˜
#[cached(service = "user_cache", ttl = 600)]
async fn get_user(id: u64) -> Result<User, String> {
    // ๆจกๆ‹Ÿ่€—ๆ—ถ็š„ๆ•ฐๆฎๅบ“ๆŸฅ่ฏข
    tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    Ok(User {
        id,
        name: format!("User {}", id),
    })
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // ๅˆๅง‹ๅŒ–็ผ“ๅญ˜๏ผˆไปŽ้…็ฝฎๆ–‡ไปถๅŠ ่ฝฝ๏ผ‰
    oxcache::init("config.toml").await?;
    
    // ็ฌฌไธ€ๆฌก่ฐƒ็”จ๏ผšๆ‰ง่กŒๅ‡ฝๆ•ฐ้€ป่พ‘ + ็ผ“ๅญ˜็ป“ๆžœ๏ผˆ~100ms๏ผ‰
    let user = get_user(1).await?;
    println!("First call: {:?}", user);
    
    // ็ฌฌไบŒๆฌก่ฐƒ็”จ๏ผš็›ดๆŽฅไปŽ็ผ“ๅญ˜่ฟ”ๅ›ž๏ผˆ~0.1ms๏ผ‰
    let cached_user = get_user(1).await?;
    println!("Cached call: {:?}", cached_user);
    
    Ok(())
}
```

### ้…็ฝฎๆ–‡ไปถ

ๅˆ›ๅปบ `config.toml`๏ผš

```toml
[global]
default_ttl = 3600
health_check_interval = 30
serialization = "json"
enable_metrics = true

[services.user_cache]
cache_type = "two-level"  # "l1" | "l2" | "two-level"
ttl = 600

  [services.user_cache.l1]
  max_capacity = 10000
  ttl = 300  # L1 TTL ๅฟ…้กป <= L2 TTL
  tti = 180
  initial_capacity = 1000

  [services.user_cache.l2]
  mode = "standalone"  # "standalone" | "sentinel" | "cluster"
  connection_string = "redis://127.0.0.1:6379"

  [services.user_cache.two_level]
  write_through = true
  promote_on_hit = true
  enable_batch_write = true
  batch_size = 100
  batch_interval_ms = 50
```

## ๐ŸŽจ ไฝฟ็”จๅœบๆ™ฏ

### ๅœบๆ™ฏ 1: ็”จๆˆทไฟกๆฏ็ผ“ๅญ˜

```rust
#[cached(service = "user_cache", ttl = 600)]
async fn get_user_profile(user_id: u64) -> Result<UserProfile, Error> {
    database::query_user(user_id).await
}
```

### ๅœบๆ™ฏ 2: API ๅ“ๅบ”็ผ“ๅญ˜

```rust
#[cached(
    service = "api_cache",
    ttl = 300,
    key = "api_{endpoint}_{version}"
)]
async fn fetch_api_data(endpoint: String, version: u32) -> Result<ApiResponse, Error> {
    http_client::get(&format!("/api/{}/{}", endpoint, version)).await
}
```

### ๅœบๆ™ฏ 3: ไป… L1 ็ƒญๆ•ฐๆฎ็ผ“ๅญ˜

```rust
#[cached(service = "session_cache", cache_type = "l1", ttl = 60)]
async fn get_user_session(session_id: String) -> Result<Session, Error> {
    session_store::load(session_id).await
}
```

### ๅœบๆ™ฏ 4: ๆ‰‹ๅŠจๆŽงๅˆถ็ผ“ๅญ˜

```rust
use oxcache::{get_client, CacheOps};

async fn advanced_caching() -> Result<(), Box<dyn std::error::Error>> {
    let client = get_client("custom_cache")?;
    
    // ๆ ‡ๅ‡†ๆ“ไฝœ
    client.set("key", &my_data, Some(300)).await?;
    let data: MyData = client.get("key").await?.unwrap();
    
    // ไป…ๅ†™ๅ…ฅ L1๏ผˆไธดๆ—ถๆ•ฐๆฎ๏ผ‰
    client.set_l1_only("temp_key", &temp_data, Some(60)).await?;
    
    // ไป…ๅ†™ๅ…ฅ L2๏ผˆๅ…ฑไบซๆ•ฐๆฎ๏ผ‰
    client.set_l2_only("shared_key", &shared_data, Some(3600)).await?;
    
    // ๅˆ ้™ค
    client.delete("key").await?;
    
    Ok(())
}
```

## ๐Ÿ—๏ธ ๆžถๆž„่ฎพ่ฎก

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    Application Code                      โ”‚
โ”‚                  (#[cached] Macro)                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                       โ”‚
                       โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                   CacheManager                           โ”‚
โ”‚        (Service Registry + Health Monitor)               โ”‚
โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜
    โ”‚                                                  โ”‚
    โ†“                                                  โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ TwoLevelClientโ”‚                              โ”‚ L1OnlyClient โ”‚
โ”‚               โ”‚                              โ”‚ L2OnlyClient โ”‚
โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜                              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
    โ”‚      โ”‚
    โ†“      โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  L1    โ”‚ โ”‚                L2                       โ”‚
โ”‚ (Moka) โ”‚ โ”‚              (Redis)                    โ”‚
โ”‚        โ”‚ โ”‚                                        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

**L1**: ่ฟ›็จ‹ๅ†…้ซ˜้€Ÿ็ผ“ๅญ˜๏ผŒไฝฟ็”จ LRU/TinyLFU ๆท˜ๆฑฐ็ญ–็•ฅ  
**L2**: ๅˆ†ๅธƒๅผๅ…ฑไบซ็ผ“ๅญ˜๏ผŒๆ”ฏๆŒ Sentinel/Cluster ๆจกๅผ

## ๐Ÿ“Š ๆ€ง่ƒฝๅŸบๅ‡†

> ๆต‹่ฏ•็Žฏๅขƒ: M1 Pro, 16GB RAM, macOS

```
ๅ•็บฟ็จ‹ๅปถ่ฟŸๆต‹่ฏ• (P99):
โ”œโ”€โ”€ L1 ็ผ“ๅญ˜:  ~50ns
โ”œโ”€โ”€ L2 ็ผ“ๅญ˜:  ~1ms
โ””โ”€โ”€ ๆ•ฐๆฎๅบ“:   ~10ms

ๅžๅ้‡ๆต‹่ฏ• (batch_size=100):
โ”œโ”€โ”€ ๅ•ๆฌกๅ†™ๅ…ฅ:  ~10K ops/s
โ””โ”€โ”€ ๆ‰น้‡ๅ†™ๅ…ฅ:  ~50K ops/s
```

## ๐Ÿ›ก๏ธ ๅฏ้ ๆ€ง

- โœ… ๅ•ๆฌก่ฏทๆฑ‚ๅŽป้‡ (Single-Flight)
- โœ… ้ข„ๅ†™ๆ—ฅๅฟ— (WAL) ๆŒไน…ๅŒ–
- โœ… Redis ๆ•…้šœ่‡ชๅŠจ้™็บง
- โœ… ไผ˜้›…ๅ…ณ้—ญๆœบๅˆถ
- โœ… ๅฅๅบทๆฃ€ๆŸฅไธŽ่‡ชๅŠจๆขๅค

## ๐Ÿ“š ๆ–‡ๆกฃ

- [๐Ÿ“– ็”จๆˆทๆŒ‡ๅ—]docs/zh/USER_GUIDE.md
- [๐Ÿ“˜ API ๆ–‡ๆกฃ]https://docs.rs/oxcache
- [๐Ÿ’ป ็คบไพ‹ไปฃ็ ]../examples/

## ๐Ÿค ่ดก็Œฎ

ๆฌข่ฟŽๆไบค Pull Request ๅ’Œ Issue๏ผ

## ๐Ÿ“ ๆ›ดๆ–ฐๆ—ฅๅฟ—

่ฏฆ่ง [CHANGELOG.md](../CHANGELOG.md)

## ๐Ÿ“„ ่ฎธๅฏ่ฏ

ๆœฌ้กน็›ฎ้‡‡็”จ MIT ่ฎธๅฏ่ฏใ€‚่ฏฆ่ง [LICENSE](../LICENSE) ๆ–‡ไปถใ€‚

---

<div align="center">

**ๅฆ‚ๆžœ่ฟ™ไธช้กน็›ฎๅฏนไฝ ๆœ‰ๅธฎๅŠฉ๏ผŒ่ฏท็ป™ไธช โญ Star ๆ”ฏๆŒไธ€ไธ‹๏ผ**

Made with โค๏ธ by oxcache Team

</div>