Rust

Rust client for ChronDB, a time-traveling key/value database built on Git architecture.

Requirements

  • Rust 1.56+ (2021 edition)

  • libclang (for bindgen to generate FFI bindings)

Stack Size (Handled Automatically)

ChronDB uses GraalVM native-image with Apache Lucene and JGit, which require deep call stacks (~64MB).

This is handled automatically. The Rust binding spawns a dedicated worker thread with a 64MB stack for all FFI operations. You do not need to configure RUST_MIN_STACK, ulimit, or any other stack settings.

The worker thread architecture also provides:

  • Consistent stack size across all platforms

  • No special CI configuration required

  • Thread-safe operation via message passing

Installation

Add chrondb from crates.ioarrow-up-right:

cargo add chrondb

Or add it directly to your Cargo.toml:

Native shared library

The crate requires the libchrondb native library at runtime. Download it from the latest GitHub releasearrow-up-right:

macOS (Apple Silicon):

Linux (x86_64):

Configure the runtime library path

The shared library must be discoverable at runtime:

Linux:

macOS:

Library path (advanced)

To override the library location at build time, set CHRONDB_LIB_DIR:

Quick Start

Legacy API (deprecated): ChronDB::open("/tmp/data", "/tmp/index") still works but is deprecated. Use open_path instead.

API Reference

ChronDB::open_path(db_path) -> Result<ChronDB>

Opens a database connection using a single directory path. Data and index are stored in subdirectories automatically.

Parameter
Type
Description

db_path

&str

Path for the database (data and index stored inside)

Returns: Result<ChronDB>

Errors: IsolateCreationFailed, OpenFailed(reason)


ChronDB::open(data_path, index_path) -> Result<ChronDB> (deprecated)

Deprecated. Use open_path instead. This method still works but will be removed in a future release.

Opens a database connection with separate data and index paths.

Parameter
Type
Description

data_path

&str

Path for the Git repository (data storage)

index_path

&str

Path for the Lucene index

Returns: Result<ChronDB>

Errors: IsolateCreationFailed, OpenFailed(reason)


ChronDB::builder(data_path, index_path) -> ChronDBBuilder

Creates a builder for opening a database with custom options like idle timeout.

Parameter
Type
Description

data_path

&str

Path for the Git repository (data storage)

index_path

&str

Path for the Lucene index

Returns: ChronDBBuilder

ChronDBBuilder::idle_timeout(duration) -> Self

Sets the idle timeout for the GraalVM isolate. When no operations happen for the specified duration, the isolate is automatically closed to free CPU and memory. The next operation transparently reopens it.

Parameter
Type
Description

duration

Duration

Max idle time before suspending the isolate

ChronDBBuilder::open() -> Result<ChronDB>

Opens the database with the configured options.

Errors: IsolateCreationFailed, OpenFailed(reason)

Example


put(&self, id, doc, branch) -> Result<serde_json::Value>

Saves a document.

Parameter
Type
Description

id

&str

Document ID (e.g., "user:1")

doc

&serde_json::Value

Document data as JSON value

branch

Option<&str>

Branch name (None for default)

Returns: The saved document as serde_json::Value.

Errors: OperationFailed(reason)


get(&self, id, branch) -> Result<serde_json::Value>

Retrieves a document by ID.

Parameter
Type
Description

id

&str

Document ID

branch

Option<&str>

Branch name

Returns: The document as serde_json::Value.

Errors: NotFound, OperationFailed(reason)


delete(&self, id, branch) -> Result<()>

Deletes a document by ID.

Parameter
Type
Description

id

&str

Document ID

branch

Option<&str>

Branch name

Returns: Ok(()) on success.

Errors: NotFound, OperationFailed(reason)


list_by_prefix(&self, prefix, branch) -> Result<serde_json::Value>

Lists documents whose IDs start with the given prefix.

Parameter
Type
Description

prefix

&str

ID prefix to match

branch

Option<&str>

Branch name

Returns: JSON array of matching documents (empty array if none).


list_by_table(&self, table, branch) -> Result<serde_json::Value>

Lists all documents in a table.

Parameter
Type
Description

table

&str

Table name

branch

Option<&str>

Branch name

Returns: JSON array of matching documents (empty array if none).


history(&self, id, branch) -> Result<serde_json::Value>

Returns the change history of a document.

Parameter
Type
Description

id

&str

Document ID

branch

Option<&str>

Branch name

Returns: JSON array of history entries (empty array if none).


query(&self, query, branch) -> Result<serde_json::Value>

Executes a query against the Lucene index.

Parameter
Type
Description

query

&serde_json::Value

Query in Lucene AST format

branch

Option<&str>

Branch name

Returns: Results object with results, total, limit, offset.

Errors: OperationFailed(reason)


execute_sql(&self, sql, branch) -> Result<serde_json::Value>

Executes a SQL query directly against the database without needing a running server.

Parameter
Type
Description

sql

&str

SQL query string

branch

Option<&str>

Branch name (None for default)

Returns: Result object with type, columns, rows, count.

Errors: OperationFailed(reason)


last_error(&self) -> Option<String>

Returns the last error message from the native library, if any.


Drop

The ChronDB struct implements Drop. When it goes out of scope, the database connection is closed and the GraalVM isolate is torn down automatically.

Document ID Convention

Documents use the format table:id:

Internally, user:123 is stored as user/user_COLON_123.json in the Git repository.

Use list_by_table("user") to retrieve all documents in the user table.

Error Handling

ChronDBError Enum

All variants implement Display and std::error::Error.

The crate also provides a type alias:

Conversion

serde_json::Error is automatically converted to ChronDBError::JsonError via From.

Example

Examples

Full CRUD

Query

History (Time Travel)

SQL Queries

Execute SQL queries directly without needing a running server:

Using with Drop (automatic cleanup)

Idle Timeout (long-running services)

ChronDB loads a GraalVM native-image shared library whose internal threads consume CPU even when no operations are in flight. For long-running services with sporadic database access, use idle_timeout to automatically suspend the isolate when idle:

When to use:

  • Long-running daemons that write to ChronDB intermittently (e.g., audit logging, MCP servers)

  • Services where memory/CPU usage matters during idle periods

When NOT to use:

  • Short-lived CLI tools (just use ChronDB::open)

  • High-throughput services with constant database access (the isolate would never go idle)

Building from Source

build.rs Behavior

The build script (build.rs):

  1. Reads CHRONDB_LIB_DIR (defaults to ../../target)

  2. Configures rustc-link-search and rustc-link-lib=dylib=chrondb

  3. If libchrondb.h and graal_isolate.h exist in that directory, generates FFI bindings via bindgen

  4. Otherwise, uses stub bindings (src/ffi_stub.rs) to allow compilation without the native library

Last updated

Was this helpful?