Skip to content

Commit

Permalink
add README
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgazelka committed Jan 18, 2025
1 parent c9b676b commit 5fe2a39
Showing 1 changed file with 96 additions and 0 deletions.
96 changes: 96 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# smart-cache

A Rust library for smart function caching with automatic invalidation. Cache expensive function calls with a simple attribute macro.

## Features

- Simple `#[cached]` attribute macro for function caching
- Persistent caching using [redb](https://github.com/cberner/redb)
- Automatic cache invalidation based on function AST analysis
- Thread-safe
- Support for complex function arguments

## Installation

Add the following to your `Cargo.toml`:

```toml
[dependencies]
smart-cache = "0.1"
```

## Key Features

### Persistent Caching
Unlike in-memory caches, smart-cache persists results between program runs. Once a function result is cached, it remains available even after restarting your application. The cache is stored in a local database using redb.

### Smart Invalidation
The library analyzes the Abstract Syntax Tree (AST) of your cached functions. If you modify the function's implementation, smart-cache automatically detects the change and invalidates the cache. This ensures you never get stale results when the function logic changes.

## Example

```rust
use smart_cache_macro::cached;

// First run of your program:
#[cached]
fn expensive_computation(x: String, y: i32) -> String {
println!("Computing..."); // We'll see when the function actually runs
std::thread::sleep(std::time::Duration::from_secs(3));
format!("example computation {}_{}", x, y)
}

fn main() {
// First call: takes 3 seconds, prints "Computing..."
let result1 = expensive_computation("hello".to_string(), 2);
println!("{}", result1); // "example computation hello_2"

// Second call: instant, no "Computing..." message
let result2 = expensive_computation("hello".to_string(), 2);
println!("{}", result2); // "example computation hello_2"
}

// If you restart your program, the cache persists:
fn main() {
// Still instant, no "Computing..." message, uses cached result from previous run
let result = expensive_computation("hello".to_string(), 2);
println!("{}", result); // "example computation hello_2"
}

// If you modify the function, the cache invalidates automatically:
#[cached]
fn expensive_computation(x: String, y: i32) -> String {
println!("Computing...");
std::thread::sleep(std::time::Duration::from_secs(3));
format!("new computation {}_{}", x, y) // Changed the string
}

fn main() {
// Cache was invalidated due to function change
// Takes 3 seconds and prints "Computing..." again
let result = expensive_computation("hello".to_string(), 2);
println!("{}", result); // "new computation hello_2"
}
```

## How it Works

The `#[cached]` attribute macro automatically:
1. Serializes function arguments
2. Stores results in a persistent database
3. Returns cached results for subsequent calls with the same arguments
4. Handles concurrent access safely

## License

Licensed under either of:
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

## Contributing

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

0 comments on commit 5fe2a39

Please sign in to comment.