# fncache
[](https://crates.io/crates/fncache)
[](https://docs.rs/fncache)
[](https://opensource.org/licenses/MIT)
A zero-boilerplate Rust library for function-level caching with pluggable backends, inspired by `functools.lru_cache` and `request-cache`.
## Features
- **ð Zero Boilerplate**: Simple `#[fncache]` attribute for instant caching
- **ð Pluggable Backends**: Memory, File, Redis, RocksDB support
- **⥠Async/Sync**: Seamless support for both synchronous and asynchronous functions
- **ðĄïļ Type Safety**: Strong typing throughout the caching layer with compile-time guarantees
- **ð Advanced Metrics**: Built-in instrumentation with latency, hit rates, and size tracking
- **ð·ïļ Cache Invalidation**: Tag-based and prefix-based cache invalidation
- **ðĨ Background Warming**: Proactive cache population for improved performance
## Quick Start
Add `fncache` to your `Cargo.toml` with the desired features:
```toml
[dependencies]
fncache = { version = "0.1", features = ["memory"] }
```
### Basic Usage
```rust
use fncache::{
backends::memory::MemoryBackend,
init_global_cache,
fncache,
Result,
};
#[fncache(ttl = 60)]
fn expensive_operation(x: u64) -> u64 {
println!("Performing expensive operation for {}", x);
std::thread::sleep(std::time::Duration::from_secs(1));
x * x
}
#[tokio::main]
async fn main() -> Result<()> {
// Initialize with memory backend
init_global_cache(MemoryBackend::new())?;
// First call executes the function
let result1 = expensive_operation(5);
println!("Result 1: {}", result1); // Takes ~1 second
// Second call returns cached result
let result2 = expensive_operation(5);
println!("Result 2: {}", result2); // Returns immediately
Ok(())
}
```
### Async Function Example
```rust
use std::time::Duration;
use tokio::time::sleep;
#[fncache(ttl = 300)]
async fn fetch_data(id: &str) -> String {
println!("Fetching data for {}", id);
sleep(Duration::from_secs(1)).await;
format!("Data for {}", id)
}
```
## Backend Examples
### Redis Backend
```rust
use fncache::backends::redis::RedisBackend;
#[tokio::main]
async fn main() -> Result<()> {
let backend = RedisBackend::new("redis://localhost:6379")?;
init_global_cache(backend)?;
// Your cached functions work the same way
Ok(())
}
```
### File Backend
```rust
use fncache::backends::file::FileBackend;
fn main() -> Result<()> {
let backend = FileBackend::new("/tmp/cache")?;
init_global_cache(backend)?;
Ok(())
}
```
## Available Features
| `memory` | In-memory cache backend | â
|
| `redis-backend` | Redis backend support | â |
| `file-backend` | File-based persistent cache | â |
| `rocksdb-backend` | RocksDB high-performance backend | â |
| `metrics` | Performance metrics collection | â
|
| `invalidation` | Tag-based cache invalidation | â
|
## Requirements
- **Rust**: 1.70 or later
- **Runtime**: `tokio` for async support
- **Dependencies**: Automatically managed via features
## Performance
- **Memory Backend**: ~1-2Ξs set latency, ~850-970Ξs get hit latency
- **Redis Backend**: ~1ms cache hit latency (network dependent)
- **File Backend**: ~100Ξs cache hit latency
- **Throughput**: Thousands of operations/second (memory backend)
See `benches/` for detailed benchmarks.
## Documentation
- **[Architecture](ARCHITECTURE.md)** - Internal design and architecture
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for version history and breaking changes.
## License
MIT License - see [LICENSE](LICENSE) for details.