TessariKV
Get started

Get started

Add the crate, open a database, write a batch.

TessariKV is a library: there is no server to run. It needs Rust 1.89 or newer and a tokio runtime. It is in early development (0.0.x): the API and the on-disk format may change in any release before 1.0, so pin the version you build against.

Install

One dependency, and tokio.

shellshell
cargo add tessarikv@0.0.2
cargo add tokio --features macros,rt-multi-thread

First write

Write a key, read it back.

DbOptions::in_memory() keeps the whole database in memory, which is the quickest way to try it; give Db::open a directory and default options for a database on disk. Close it when you are done: a running flush finishes, every acknowledged write is synced and the directory is released.

src/main.rsrust
use tessarikv::{Db, DbOptions, KeyspaceId, ReadOptions, WriteBatch, WriteOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = Db::open("example", DbOptions::in_memory()).await?;

    let mut batch = WriteBatch::new();
    batch.put(KeyspaceId::DEFAULT, b"apple", b"red")?;
    db.write(&batch, &WriteOptions::default()).await?;

    let value = db.get(KeyspaceId::DEFAULT, b"apple", &ReadOptions::default()).await?;
    assert_eq!(value.as_deref(), Some(&b"red"[..]));

    db.close().await?;
    Ok(())
}

Durability

Say how durable each write must be.

The default is Durability::Sync: the log record is on stable storage before write returns. A write that can afford to lose the last moments before a machine failure hands its record to the operating system instead, and a bulk load that can be redone skips the log entirely.

durabilityrust
use tessarikv::{Durability, WriteOptions};

let mut fast = WriteOptions::default();
fast.durability = Durability::Buffered; // survives a process crash
db.write(&batch, &fast).await?;

db.sync_wal().await?; // and now everything written so far is durable

Transactions

Read at a snapshot, commit as one batch.

A transaction reads as of the moment it began, sees its own writes, and commits them atomically. If another commit touched a key it writes after it began, commit is refused with Conflict and writes nothing; run it again.

transactionrust
let mut txn = db.begin()?;
txn.put(KeyspaceId::DEFAULT, b"apple", b"green")?;
let own = txn.get(KeyspaceId::DEFAULT, b"apple", &ReadOptions::default()).await?;
assert_eq!(own.as_deref(), Some(&b"green"[..]));
txn.commit(&WriteOptions::default()).await?;

From source

Building and testing the engine.

The last command model-checks the lock-free building blocks under loom. Before a change goes in, formatting, clippy with warnings denied (also for Linux and Windows targets) and cargo deny pass.

shellshell
git clone https://github.com/tessaridb/tessarikv && cd tessarikv
cargo build --workspace
cargo test --workspace --tests
RUSTFLAGS="--cfg loom" LOOM_MAX_PREEMPTIONS=3 cargo test -p tessarikv-sync --release --lib