中に組み込む
ストアを、
そのものの中へ
サーバーもソケットもネットワークもありません。エンジンは、呼び出せる struct であり、151 KB の WebAssembly モジュールであり、OS のないチップの上の no_std ライブラリです——そして 3 つとも、同じコマンドを持つ、同じエンジンです。
なぜ向いているのか
オフラインで動く必要のあるアプリケーションは、どれも結局ストレージ層を書くことになります。デスクトップアプリは SQLite と、誰も望まなかったスキーマを手に入れます。Web アプリは localStorage を使い、5 MB の上限と、同期でしかも文字列しか扱えないという事実を知り、次に IndexedDB とその上の抽象を手に入れます。デバイスは、フラッシュ上に手書きのリングバッファを手に入れます。
3 つとも同じ問題であり、同じ解になりえます。kevy はプロセス境界なしで組み込め、本物の TTL と pub/sub を持ったままブラウザに届き、固定 arena とアロケータなしで Cortex-M でも起動します。最後のひとつは、CI が push のたびに証明しています。
手順——Rust のプログラムの中で
kevy-embedded = "4.0"
let db = Db::open("data/")?;
db.set(b"session:7f3a", b"{\"user\":\"ada\"}", Some(Duration::from_secs(3600)))?;
assert_eq!(db.get(b"session:7f3a")?.is_some(), true);
// need other processes to reach it later? open the RESP listener
// and your redis-cli works, without changing any of the above.
db.listen("127.0.0.1:6379")?;手順——ブラウザのタブで
import { open } from "@goliajp/kevy";
const db = await open({ persist: { name: "app" } });
db.set("cart:u881", JSON.stringify(items), { ttlMs: 86_400_000 });
db.get("cart:u881"); // still there after a reload
db.pttl("cart:u881"); // the engine expires it, not your code
db.subscribe("sync", (payload) => merge(payload)); // other tabs手順——マイコンの上で
# Cargo.toml
kevy-store = { version = "4.0", default-features = false }
# no_std, no heap: the store lives in an arena you provide
let mut arena = [0u8; 64 * 1024];
let mut store = Store::new_in(&mut arena);
store.set(b"temp", b"21.4")?;ブラウザでは、小さな同期の読み取りなら localStorage のほうが速いです——あれはページ自身のアドレス空間にあるマップであり、OPFS の上に作られたものが、そこで勝つことはありません。kevy が勝つのは、そもそも localStorage を選ぶべきでない理由のほうです。本物の TTL、5 MB の上限がないこと、値が文字列ではなくバイト列であること、書き込みがメインスレッドを止めないこと。マイコンでは、arena の大きさを自分で決めますし、実行中に広げることはできません。アロケータがないとは、そういうことです。そして組み込みのストアは共有されません。2 つ目のプロセスがデータを必要とするなら、必要なのはサーバーか、組み込みの RESP リスナーです。