contextdb-engine 0.3.3

Embedded database engine for agentic memory — relational, graph, and vector under unified MVCC transactions
Documentation
use contextdb_core::{Direction, Value};
use contextdb_engine::Database;
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::path::PathBuf;
use uuid::Uuid;

fn main() {
    if let Err(err) = run() {
        eprintln!("{err}");
        std::process::exit(1);
    }
}

fn run() -> Result<(), Box<dyn Error>> {
    let db_path = env::args_os()
        .nth(1)
        .map(PathBuf::from)
        .ok_or("missing database path argument")?;

    println!("WORKLOAD_START");

    let db = Database::open(&db_path)?;
    db.execute(
        "CREATE TABLE rss_items (id UUID PRIMARY KEY, name TEXT, embedding VECTOR(16))",
        &HashMap::new(),
    )?;

    let mut chain = Vec::<Uuid>::new();
    let mut batches = 0usize;
    for batch in 0..8usize {
        let tx = db.begin();
        for i in 0..250usize {
            let ordinal = batch * 250 + i;
            let node_id = Uuid::from_u128(ordinal as u128 + 1);
            let row_id = db.insert_row(
                tx,
                "rss_items",
                HashMap::from([
                    ("id".to_string(), Value::Uuid(node_id)),
                    (
                        "name".to_string(),
                        Value::Text(format!("rss-item-{ordinal:04}")),
                    ),
                ]),
            )?;
            let vector = (0..16usize)
                .map(|j| ((ordinal + j) % 17) as f32 / 17.0)
                .collect::<Vec<_>>();
            db.insert_vector(tx, row_id, vector)?;
            if let Some(&previous) = chain.last() {
                db.insert_edge(
                    tx,
                    previous,
                    node_id,
                    "DEPENDS_ON".to_string(),
                    HashMap::new(),
                )?;
            }
            chain.push(node_id);
        }
        db.commit(tx)?;
        batches += 1;
    }

    let reopened = Database::open(&db_path)?;
    let snapshot = reopened.snapshot();
    let rows = reopened.scan("rss_items", snapshot)?;
    assert_eq!(rows.len(), 2000, "all relational rows must survive reopen");

    let bfs = reopened.query_bfs(Uuid::from_u128(1), None, Direction::Outgoing, 2, snapshot)?;
    assert!(
        !bfs.nodes.is_empty(),
        "graph traversal after reopen must return reachable nodes"
    );

    let vector_results = reopened.query_vector(&[0.0; 16], 5, None, snapshot)?;
    assert!(
        !vector_results.is_empty(),
        "vector query after reopen must return persisted rows"
    );

    println!(
        "WORKLOAD_DONE batches={batches} rows={} graph_nodes={} vector_hits={}",
        rows.len(),
        bfs.nodes.len(),
        vector_results.len()
    );
    Ok(())
}