Docs
  • 0.0.2latest

Getting started

Add the crate, open a database on disk or in memory, write a batch, read it back and close the handle.

TessariKV needs Rust 1.89 or newer and a tokio runtime.

Add it

cargo add tessarikv
cargo add tokio --features macros,rt-multi-thread

Open, write, read

use tessarikv::{Db, DbOptions, KeyspaceId, ReadOptions, WriteBatch, WriteOptions};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // A directory on disk; it is created when it holds no database.
    let db = Db::open("data/inventory", DbOptions::default()).await?;

    let mut batch = WriteBatch::new();
    batch.put(KeyspaceId::DEFAULT, b"sku:1001", b"12 in stock")?;
    batch.put(KeyspaceId::DEFAULT, b"sku:1002", b"out of stock")?;
    db.write(&batch, &WriteOptions::default()).await?;

    let value = db.get(KeyspaceId::DEFAULT, b"sku:1001", &ReadOptions::default()).await?;
    assert_eq!(value.as_deref(), Some(&b"12 in stock"[..]));

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

A WriteBatch method fails with the table format's own error type, which tessarikv::Error does not convert from, so code that builds batches returns a boxed error, as here.

WriteOptions::default() waits until the log record is on stable storage, so the write survives a power loss. Writes and durability covers the cheaper choices.

In memory only

DbOptions::in_memory() runs the same engine with every file held in process memory. Nothing survives the process. It suits tests and caches.

use tessarikv::{Db, DbOptions};

async fn scratch() -> tessarikv::Result<Db> {
    // The path only names the database; nothing is written to disk.
    Db::open("scratch", DbOptions::in_memory()).await
}

Options

DbOptions::builder() starts from the defaults and validates on build().

use tessarikv::{DbOptions, WalRecovery};

fn options() -> tessarikv::Result<DbOptions> {
    DbOptions::builder()
        .block_cache_bytes(1 << 30) // 1 GiB of block cache
        .background_threads(8)
        .wal_recovery(WalRecovery::Absolute)
        .build()
}

A value out of range is refused with Error::InvalidOptions, which names the option. Every option and its default is on Options.

One handle per directory

While a database is open, its directory is locked: another process opening the same path is refused with Error::Locked. Within one program, share one Db between tasks: every method takes &self, so wrap it in an Arc.

Db::close lets a running flush finish, writes and syncs every acknowledged write, then releases the lock. Dropping the handle without closing it leaves the log writer to finish in the background, unobserved.