5 releases (3 breaking)
0.5.0 |
|
---|---|
0.4.0 | Oct 21, 2024 |
0.3.0 | Oct 18, 2024 |
0.2.0 | Oct 17, 2024 |
0.1.1 | Oct 14, 2024 |
#62 in Caching
115 downloads per month
73KB
1.5K
SLoC
Kash
Caching structures and simplified function memoization, using #[kash]
macro.
use kash::kash;
/// Defines a function named `fib` that uses a cache implicitly named `FIB`.
/// By default, the cache will be the function's name in all caps.
#[kash]
fn fib(n: u64) -> u64 {
if n == 0 || n == 1 { return n }
fib(n-1) + fib(n-2)
}
Or if you want to limit the size and time-to-live:
use kash::kash;
const TTL: u64 = 1000;
#[kash(size = "100", ttl = "TTL")]
fn fib(n: u64) -> u64 {
if n == 0 || n == 1 { return n }
fib(n-1) + fib(n-2)
}
Features
default
: Includesahash
feature.ahash
: Enableahash
hasher as default hashing algorithm.async
: Include support for async functions.redis_store
: Include Redis cache store.redis_async_std
: Include async Redis support usingasync-std
andasync-std
tls support, impliesredis_store
andasync
.redis_tokio
: Include async Redis support usingtokio
andtokio
tls support, impliesredis_store
andasync
.redis_connection_manager
: Enable the optionalconnection-manager
feature ofredis
. Any async redis caches created will use a connection manager instead of aMultiplexedConnection
.redis_ahash
: Enable the optionalahash
feature ofredis
.disk_store
: Include disk cache store.
use std::thread::sleep;
use std::time::Duration;
use kash::kash;
/// Use an explicit cache-type with a custom creation block and custom cache-key generating block
#[kash(
size = "100",
key(ty = "String", expr = r#"{ format!("{}{}", a, b) }"#)
)]
fn keyed(a: &str, b: &str) -> usize {
let size = a.len() + b.len();
sleep(Duration::new(size as u64, 0));
size
}
use kash::{kash, RedisCacheError};
use kash::AsyncRedisCache;
use thiserror::Error;
#[derive(Error, Debug, PartialEq, Clone)]
enum ExampleError {
#[error("error with redis cache `{0}`")]
RedisError(String),
}
impl From<RedisCacheError> for ExampleError {
fn from(e: RedisCacheError) -> Self {
ExampleError::RedisError(format!("{:?}", e))
}
}
/// Cache the results of an async function in redis. Cache
/// keys will be prefixed with `cache_redis_prefix`.
#[kash(redis)]
async fn async_kash_sleep_secs(secs: u64) -> Result<String, ExampleError> {
std::thread::sleep(std::time::Duration::from_secs(secs));
Ok(secs.to_string())
}
use kash::{kash, DiskCacheError};
use kash::DiskCache;
use thiserror::Error;
#[derive(Error, Debug, PartialEq, Clone)]
enum ExampleError {
#[error("error with disk cache `{0}`")]
DiskError(String),
}
impl From<DiskCacheError> for ExampleError {
fn from(e: DiskCacheError) -> Self {
ExampleError::DiskError(format!("{:?}", e))
}
}
/// Cache the results of a function on disk.
/// Cache files will be stored under the system cache dir
/// unless otherwise specified with `dir` or the `create` argument.
#[kash(disk)]
fn kash_sleep_secs(secs: u64) -> Result<String, ExampleError> {
std::thread::sleep(std::time::Duration::from_secs(secs));
Ok(secs.to_string())
}
Functions defined via macros will have their result, cached using the function's arguments as a key by default.
When a macro-defined function is called, the function's cache is first checked for an already computed (and still valid) value before evaluating the function body.
See examples
directory for more examples.
License
MIT
Dependencies
~4–18MB
~252K SLoC