🐷

jaemk/cached を使ってRust(axum)で動くサーバーでキャッシュ出来るか試してみた

2022/03/05に公開

TL;DR

簡単なキャッシュ(関数のメモ化)は jaemk/cached で実現できる。
https://crates.io/crates/cached
https://github.com/jaemk/cached

サンプルコード

https://github.com/yyYank/rust-sandbox/tree/master/cache-sample

use axum::Router;
use axum::routing::get;
use axum::extract;
use cached::{async_mutex, Cached, UnboundCache};
use cached::proc_macro::cached;

/*
cached! {
    TWICE_CACHE: SizedCache<String, String> = SizedCache::with_size(5000);
    fn cached_twice(id:String) -> String = {
        println!("{} not cached", id);
        return (id.parse::<i32>().unwrap() * 2).to_string();
    }
}
 */

#[cached (name="TWICE_CACHE")]
async fn cached_twice(id:String) -> String {
    println!("{} not cached", id);
    return format!("{} * 2 = {}", id, id.parse::<i32>().unwrap() * 2);
}

pub fn routes() -> Router{
    Router::new()
        .route("/cache/:id", get(get_cache))
        .route("/clear-cache/:id", get(clear_cache))
}

async fn get_cache(
    extract::Path(id) : extract::Path<String>
) -> String {
    cached_twice(id).await
}

async fn clear_cache(
    extract::Path(id) : extract::Path<String>
) -> String {
    {
        let mut cache : async_mutex::MutexGuard<UnboundCache<String, String>>= TWICE_CACHE.lock().await;
        cache.cache_remove(&id);
    }
    return format!("{} cache clear has done", id);
}

何をやっているか

  • 簡単なリクエストを2倍して返すAPIサンプル
  • /cache/:id で1回目にキャッシュ
  • /cache/:id で2回目以降はキャッシュされた値が返される
  • /clear-cache/:id でキャッシュクリア
  • 面倒だったので全部GETにしちゃったけど許して欲しい

使い方

cachedは関数の結果をキャッシュしてくれるマクロを提供してくれる。
Function-likeマクロ(Function-like macros)とattribute(Attribute macros)マクロの書き方が出来る。

ただasyncな関数に対してはどうやらattributeマクロの方式でしか対応してくれないようで
Function-likeマクロの書き方だとエラーになった。

axumとかasyncをつけたい場合はattributeマクロ一択になりそう。

キャッシュクリアをしたかったため、
name="TWICE_CACHE"という形でキャッシュの構造体の名前を明示するようにしている。
TWICE_CACHE はlockすることで操作できるっぽい。

この場合は async_mutex::MutexGuard<UnboundCache<String, String>> が実体の型となっている。

まとめ

雑にサーバーサイドでキャッシュしたい時はjaemk/cached良いかも。

ただサーバー再起動したら消えるし、複数サーバーだとキャッシュは共有されないしなどあるので
ちゃんとやるならredisとかが無難かも。

参考

GitHubで編集を提案

Discussion