kash

Crates.iokash
lib.rskash
version0.5.0
sourcesrc
created_at2024-10-14 12:12:09.350099
updated_at2024-10-28 15:00:03.284463
descriptionFunction and method cache and memoization
homepage
repositoryhttps://github.com/omid/kash
max_upload_size
id1408232
size162,678
Omid Rad (omid)

documentation

https://docs.rs/kash

README

Kash

crates.io version build status downloads docs.rs docs MIT licensed dependency status

Function and method cache and memoization library for Rust, 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: Includes ahash feature.
  • ahash: Enable ahash hasher as default hashing algorithm.
  • async: Include support for async functions.
  • redis_store: Include Redis cache store.
  • redis_tokio: Include async Redis support using tokio and tokio tls support, implies redis_store and async.
  • redis_connection_manager: Enable the optional connection-manager feature of redis. Any async redis caches created will use a connection manager instead of a MultiplexedConnection.
  • redis_ahash: Enable the optional ahash feature of redis.
  • 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

Commit count: 520

cargo fmt