Skip to main content

Rust API Reference

The SochDB Rust SDK is the embedded, synchronous client for the SochDB engine. It ships as the crate sochdb (source lives in the sochdb-client/ directory of the workspace).

  • Crate name: sochdb
  • Version: 2.0.3
  • License: AGPL-3.0-or-later (the core engine and this crate). Commercial licensing is available — see the project's NOTICE file. The language SDKs (Python, Node.js, Go) are Apache-2.0, but this Rust crate is part of the AGPL core.
  • Edition: 2024 (minimum Rust 1.85)
Embedded and synchronous

This crate is purely embedded and fully synchronous — there is no async API and no network/remote client. Every call blocks. For remote access, use the gRPC server (sochdb-grpc), the MCP server (sochdb-mcp), or one of the language SDKs.

Installation

[dependencies]
sochdb = "2.0.3"

Or with Cargo:

cargo add sochdb

Cargo features

FeatureDefaultEffect
defaultNo features enabled.
simdoffSIMD-accelerated distance kernels.
embeddedoffEnables EmbeddedConnection / DurableSochClient, which drive the full Database kernel directly (SQL via execute_sql, etc.).
README drift

The crate's own bundled README.md is stale — it describes an async IpcClient and version 0.3 that no longer exist. The authoritative surface is src/lib.rs plus the examples under examples/rust/, which is what this page documents.

Quick start

use sochdb::Connection;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
// Durable, WAL-backed database (creates the directory if missing).
let conn = Connection::open("./example_db")?;

// Key-value operations over byte slices.
conn.put(b"greeting", b"Hello, SochDB!")?;
let value = conn.get(b"greeting")?; // Option<Vec<u8>>

// Path-based hierarchical keys.
conn.put_path("users/alice/name", b"Alice Smith")?;
let name = conn.get_path("users/alice/name")?;

// Prefix scan.
for (key, value) in conn.scan_path("users/")? {
println!("{key} = {}", String::from_utf8_lossy(&value));
}
Ok(())
}

Connection types

All connection types live in the connection module. The crate re-exports several aliases at the root for convenience:

pub use connection::DurableConnection;
pub type Connection = DurableConnection; // default, WAL-durable
pub type Database = DurableConnection; // alias for `use sochdb::Database`
pub use connection::SochConnection;
pub type InMemoryConnection = SochConnection; // in-memory, testing
#[cfg(feature = "embedded")]
pub use connection::EmbeddedConnection;
TypeAlias(es)BackingUse for
DurableConnectionConnection, DatabaseWAL + MVCC + crash recoveryProduction durable storage.
SochConnectionInMemoryConnectionIn-memoryTests, and SQL execution (execute_sql/query_sql).
EmbeddedConnectionFull Database kernelDirect kernel access; requires the embedded feature.
ReadOnlyConnectionRead-only handleSnapshot/read-only access to an existing DB.

DurableConnection (Connection / Database)

The production connection — WAL, MVCC, and crash recovery.

// Opening
pub fn open(path: impl AsRef<Path>) -> Result<Self>;
pub fn open_with_config(path: impl AsRef<Path>, config: ConnectionConfig) -> Result<Self>;
pub fn open_ephemeral() -> Result<Self>;
pub fn open_ephemeral_with_config(config: ConnectionConfig) -> Result<Self>;

// Key-value (byte slices)
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<()>;
pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
pub fn delete(&self, key: &[u8]) -> Result<()>;
pub fn scan(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;

// Path-based
pub fn put_path(&self, path: &str, value: &[u8]) -> Result<()>;
pub fn get_path(&self, path: &str) -> Result<Option<Vec<u8>>>;
pub fn delete_path(&self, path: &str) -> Result<()>;
pub fn scan_path(&self, prefix: &str) -> Result<Vec<(String, Vec<u8>)>>;
pub fn scan_range(&self, start: &str, end: &str) -> Result<Vec<(String, Vec<u8>)>>;

// Transactions (manual)
pub fn begin_txn(&self) -> Result<u64>;
pub fn commit_txn(&self) -> Result<u64>;
pub fn abort_txn(&self) -> Result<()>;

// Fast read-transaction variants
pub fn begin_read_txn_fast(&self) -> u64;
pub fn get_path_fast(&self, /* ... */) -> Result<Option<Vec<u8>>>;
pub fn scan_path_fast(&self, /* ... */) -> Result<Vec<(String, Vec<u8>)>>;
pub fn scan_range_fast(&self, /* ... */) -> Result<Vec<(String, Vec<u8>)>>;

// Durability / maintenance
pub fn fsync(&self) -> Result<()>;
pub fn checkpoint(&self) -> Result<u64>;
pub fn gc(&self) -> Result<usize>;
pub fn recover(&self) -> Result<RecoveryResult>;

// Schema / bulk insert
pub fn register_table(&self, /* ... */) -> Result<()>;
pub fn insert_row_slice(&self, /* ... */) -> Result<()>;
pub fn bulk_insert_slice<I>(&self, table: &str, rows: I, batch_size: usize) -> Result<usize>;

// Introspection
pub fn stats(&self) -> DurableStats;
pub fn config(&self) -> &ConnectionConfig;

SochConnection (InMemoryConnection)

In-memory connection used for tests and for SQL execution.

pub fn open(path: impl AsRef<Path>) -> Result<Self>;     // path ignored; in-memory
pub fn open_persistent(path: impl AsRef<Path>) -> Result<Self>;

// Key-value (note: owned Vec<u8> for put)
pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
pub fn put(&self, key: Vec<u8>, value: Vec<u8>) -> Result<()>;
pub fn delete(&self, key: &[u8]) -> Result<()>;
pub fn scan_prefix(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;

// Transactions
pub fn begin_txn(&self) -> Result<u64>;
pub fn commit_txn(&self) -> Result<u64>;
pub fn abort_txn(&self) -> Result<()>;

// Schema
pub fn register_table(&self, /* ... */) -> Result<()>;
pub fn get_schema(&self, table: &str) -> Result<SochSchema>;
pub fn describe_table(&self, table: &str) -> Result<TableDescription>;
pub fn list_tables(&self) -> Vec<String>;
pub fn count_rows(&self, table: &str) -> Result<u64>;
pub fn resolve(&self, path: &str) -> Result<Option<Vec<u8>>>;

// Maintenance
pub fn stats(&self) -> ClientStats;
pub fn flush(&self) -> Result<usize>;
pub fn compact(&self) -> Result<CompactionMetrics>;
pub fn fsync(&self) -> Result<()>;

EmbeddedConnection (feature embedded)

Wraps the full Database kernel. Adds SQL execution and direct kernel access.

#[cfg(feature = "embedded")]
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self>;
pub fn open_with_config<P: AsRef<Path>>(path: P, config: DatabaseConfig) -> Result<Self>;
pub fn kernel(&self) -> &Arc<Database>;

pub fn begin(&self) -> Result<()>;
pub fn commit(&self) -> Result<u64>;
pub fn abort(&self) -> Result<()>;

pub fn put(&self, path: &str, value: &[u8]) -> Result<()>;
pub fn get(&self, path: &str) -> Result<Option<Vec<u8>>>;
pub fn delete(&self, path: &str) -> Result<()>;
pub fn scan(&self, prefix: &str) -> Result<Vec<(String, Vec<u8>)>>;
pub fn scan_range(&self, start: &str, end: &str) -> Result<Vec<(String, Vec<u8>)>>;

pub fn query(&self, path_prefix: &str) -> EmbeddedQueryBuilder;
pub fn execute_sql(&self, sql: &str) -> Result<ExecutionResult>;
pub fn execute_sql_params(&self, sql: &str, params: &[SochValue]) -> Result<ExecutionResult>;

pub fn db_stats(&self) -> DatabaseStats;
// plus checkpoint / truncate_wal / gc / fsync / shutdown

ConnectionConfig and durability

pub struct ConnectionConfig {
pub group_commit: bool,
pub sync_mode: Durability,
pub enable_ordered_index: bool,
pub group_commit_batch_size: usize,
pub group_commit_max_wait_us: u64,
}

pub enum Durability {
Full, // crash-durable
NormalMayLoseRecentCommits, // alias: Durability::Normal
Unsafe, // alias: Durability::Off
}
pub type SyncModeClient = Durability;

Defaults: group_commit = true, sync_mode = Durability::Full, enable_ordered_index = true, group_commit_batch_size = 100, group_commit_max_wait_us = 10_000.

Presets:

Presetsync_modeordered indexbatch / max wait
throughput_optimized()Normaloff1000 / 50_000 us
latency_optimized()Fullon10 / 1_000 us
max_durability()Full (no group commit)on1 / 0 us

Durability::is_crash_durable() returns true only for Full.

Connection traits

Higher-level overlays (graph, policy, routing, semantic cache, atomic memory) are generic over C: ConnectionTrait, so they work with any compatible connection.

pub trait ConnectionTrait {                 // put/get/delete/scan over &[u8]
fn put(&self, key: &[u8], value: &[u8]) -> Result<()>;
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn delete(&self, key: &[u8]) -> Result<()>;
fn scan(&self, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;
}
pub trait ReadableConnection { /* ... */ }
pub trait WritableConnection: ReadableConnection { /* ... */ }

Transactions

Manual transaction control is available directly on the connection (begin_txn / commit_txn / abort_txn). The transaction module adds a richer, isolation-aware handle.

pub enum IsolationLevel { /* ... */ }

pub struct ClientTransaction<'a> { /* ... */ }
impl<'a> ClientTransaction<'a> {
pub fn begin(conn: &'a SochConnection, isolation: IsolationLevel) -> Result<Self>;
pub fn id(&self) -> TxnId;
pub fn start_ts(&self) -> u64;
pub fn state(&self) -> TxnState;
pub fn isolation(&self) -> IsolationLevel;
pub fn is_read_only(&self) -> bool;

pub fn get(&mut self, table: &str, key: &[u8]) -> Result<Option<Vec<u8>>>;
pub fn put(&mut self, table: &str, key: Vec<u8>, value: Vec<u8>) -> Result<()>;
pub fn delete(&mut self, table: &str, key: Vec<u8>) -> Result<()>;

pub fn commit(self) -> Result<CommitResult>;
pub fn rollback(self) -> Result<()>;
}

pub struct SnapshotReader<'a> { /* now / at_timestamp / get / timestamp */ }
pub struct BatchWriter<'a> { /* new / write / delete / flush -> BatchCommitResult / pending_count */ }
pub struct CommitResult { /* ... */ }
pub struct BatchCommitResult { /* ... */ }

Manual transaction example:

use sochdb::Connection;

let conn = Connection::open("./txn_db")?;

conn.begin_txn()?;
conn.put(b"accounts/alice/balance", b"1000")?;
conn.put(b"accounts/bob/balance", b"500")?;
conn.commit_txn()?;

// Rollback on error
conn.begin_txn()?;
conn.put(b"accounts/alice/balance", b"9999")?;
conn.abort_txn()?; // change discarded

The SochClient facade exposes begin() (snapshot isolation), begin_with_isolation(level), and snapshot() returning a SnapshotReader.

Typed CRUD builders

The crud module adds fluent, typed builders via extension methods on the connection.

// Builders
conn.insert_into(table) -> RowBuilder<'_>;
conn.update(table) -> UpdateBuilder<'_>;
conn.delete_from(table) -> DeleteBuilder<'_>;
conn.find(table) -> FindBuilder<'_>;
conn.upsert(table, conflict_key) -> UpsertBuilder<'_>;

pub struct RowBuilder<'a> { /* set(field, impl Into<SochValue>) / row() / execute() -> InsertResult */ }
pub struct UpdateBuilder<'a> { /* set / where_eq / where_cond(field, CompareOp, val) / execute() -> UpdateResult */ }
pub struct DeleteBuilder<'a> { /* where_eq / where_cond / execute() -> DeleteResult */ }
pub struct FindBuilder<'a> {
/* select(&[&str]) / where_eq / where_cond / order_by / limit / offset
/ execute() -> Vec<HashMap<String, SochValue>> / first() / all() */
}
pub struct UpsertBuilder<'a> { /* set / row / execute() -> UpsertResult */ }

One-shot helpers: insert_one, find_by_id, delete_by_id, count(table) -> Result<u64>, exists(table, field, val) -> Result<bool>, update_where, delete_where. Result types are InsertResult, UpdateResult, DeleteResult, and UpsertResult.

Low-level path query

The path_query module provides a fluent query over the path tree:

pub enum CompareOp { /* Eq, Gt, Lt, ... */ }

pub struct PathQuery<'a> { /* ... */ }
impl<'a> PathQuery<'a> {
pub fn from_path(conn: &'a SochConnection, path: &str) -> Self;
// nested(subpath) / filter(field, CompareOp, val) / where_eq / where_gt / where_lt
// / where_like / project(&[..]) / select / order_by(col, asc) / limit / offset
pub fn execute(self) -> Result<SochResult>;
pub fn collect(self) -> Result<Vec<String>>;
pub fn to_toon(self) -> Result<String>;
}

pub struct Predicate { /* eq / gt / lt / like */ }

SQL execution

SQL runs against the in-memory SochConnection. (For durable storage, use the path-based APIs on DurableConnection, or EmbeddedConnection::execute_sql with the embedded feature.) There are three entry points:

QueryExecutor (query module)

pub struct QueryExecutor<'a> { /* ... */ }
impl<'a> QueryExecutor<'a> {
pub fn new(conn: &'a SochConnection) -> Self;
pub fn execute(&self, sql: &str) -> Result<QueryResult>;
pub fn query_rows(&self, sql: &str) -> Result<Vec<HashMap<String, SochValue>>>;
pub fn execute_sql(&self, sql: &str) -> Result<u64>;
}

Unified SQL entry point (sql_entry module)

Free functions plus prepared-statement / query-builder helpers:

pub fn execute(conn: &SochConnection, sql: &str) -> Result<QueryResult>;
pub fn execute_with_params(conn: &SochConnection, sql: &str, params: &[SochValue]) -> Result<QueryResult>;
pub fn execute_with_stats(conn: &SochConnection, sql: &str) -> Result<(QueryResult, QueryStats)>;
pub fn execute_batch(conn: &SochConnection, statements: &[&str]) -> Result<BatchResult>;

pub struct PreparedStatement<'a> { /* prepare(conn, sql) / execute(&[SochValue]) / sql() / param_count() */ }
pub struct QueryBuilder<'a> {
/* select/insert/update/delete(conn, table) / columns / set / where_eq
/ order_by / limit / offset / to_sql() -> (String, Vec<SochValue>) / execute() -> QueryResult */
}

AST-based execution (ast_query module + connection methods)

The connection exposes convenience methods backed by the AST executor:

pub fn query_ast(&self, sql: &str) -> Result<QueryResult>;
pub fn query_ast_params(&self, sql: &str, params: &[SochValue]) -> Result<QueryResult>;
pub fn query_rows_ast(&self, sql: &str) -> Result<Vec<HashMap<String, SochValue>>>;
pub fn execute_ast(&self, sql: &str) -> Result<u64>;
pub fn sql_execute(&self, sql: &str) -> Result<ExecutionResult>;
pub fn sql_execute_params(&self, sql: &str, params: &[SochValue]) -> Result<ExecutionResult>;

QueryResult is defined in ast_query and re-exported as query::QueryResult. The convenience methods used in the examples are execute_sql(sql) (write/DDL) and query_sql(sql) (read).

SQL example:

use sochdb::SochConnection;

let conn = SochConnection::open("./demo_sql_db")?;

conn.execute_sql(
"CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER)",
)?;
conn.execute_sql("INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30)")?;

let result = conn.query_sql("SELECT name, age FROM users WHERE age > 28 ORDER BY age DESC")?;
if let sochdb::ast_query::QueryResult::Select(rows) = result {
for row in &rows {
println!("{:?}", row.get("name"));
}
}
SQL feature coverage

The SQL engine supports SELECT/INSERT/UPDATE/DELETE, CREATE/DROP TABLE, CREATE/DROP INDEX, GROUP BY, HAVING, ORDER BY, LIMIT/OFFSET, and INNER/LEFT/RIGHT/FULL/CROSS joins. DISTINCT, window functions, CTEs, and subqueries in WHERE/SELECT are not yet implemented; CAST is currently a pass-through (no real type coercion). LIKE is case-sensitive and treats all non-%/_ characters (including .) literally. See the SQL API reference for the full matrix.

The vectors module provides VectorCollection over a SochConnection.

pub struct VectorCollection { /* ... */ }
impl VectorCollection {
pub fn open(conn: &Arc<SochConnection>, name: &str) -> Result<Self>;
pub fn create(conn: &Arc<SochConnection>, name: &str, dimension: usize) -> Result<Self>;

pub fn add(&mut self, ids: &[&str], vectors: &[Vec<f32>]) -> Result<()>;
pub fn add_one(&mut self, id: &str, vector: Vec<f32>) -> Result<()>;
pub fn search(&self, query: &[f32], k: usize) -> Result<Vec<SearchResult>>;
pub fn get(&self, id: &str) -> Option<Vec<f32>>;
pub fn delete(&mut self, id: &str) -> Result<bool>;
pub fn stats(&self) -> VectorStats;

// Product-quantization controls
pub fn train_pq(&mut self) -> Result<()>;
pub fn is_pq_trained(&self) -> bool;
pub fn compression_ratio(&self) -> Option<f32>;
pub fn migrate_batch(&mut self) -> Result<usize>;

pub fn name(&self) -> &str;
pub fn dimension(&self) -> usize;
pub fn len(&self) -> usize;
pub fn is_empty(&self) -> bool;
}

pub struct SearchResult {
pub id: String,
pub distance: f32,
pub metadata: Option<HashMap<String, SochValue>>,
}

pub struct VectorStats {
pub count: usize,
pub dimension: usize,
pub backend: String,
pub memory_bytes: usize,
pub pq_enabled: bool,
pub migration_progress: Option<u8>,
}

pub struct ProductQuantizer { /* new(dim, m, k) / new_default(dim) / train / encode / decode */ }

Example:

use sochdb::SochConnection;
use sochdb::vectors::VectorCollection;
use std::sync::Arc;

let conn = Arc::new(SochConnection::open("./vector_db")?);
let mut collection = VectorCollection::create(&conn, "demo", 128)?;

let ids = ["doc_0", "doc_1", "doc_2"];
let vectors: Vec<Vec<f32>> = vec![vec![0.1; 128], vec![0.2; 128], vec![0.3; 128]];
collection.add(&ids, &vectors)?;

let query = vec![0.15f32; 128];
for hit in collection.search(&query, 5)? {
println!("{} (distance {:.4})", hit.id, hit.distance);
}
No HNSW config on the SDK collection

The client VectorCollection does not expose HNSW parameters (M, ef_construction, ef_search). Its in-memory backend uses brute-force linear search; it transparently switches to a Vamana + product-quantization backend once a collection exceeds VAMANA_THRESHOLD = 100_000 vectors. The full HNSW index (with HnswConfig) lives in the separate sochdb-index crate, not in this SDK. The core engine's HnswConfig defaults are M = 32, ef_construction = 256, ef_search = 500 (a single fixed value — there is no dimension-aware ef_search split), metric Cosine, precision F32.

PQ defaults: DEFAULT_PQ_SUBSPACES = 8, DEFAULT_PQ_CENTROIDS = 256, DEFAULT_PQ_ITERATIONS = 20, MIN_PQ_TRAINING_VECTORS = 1000, DEFAULT_MIGRATION_BATCH_SIZE = 1000.

Context query

The context_query module assembles token-budgeted LLM context from prioritized sections.

pub struct ContextQueryBuilder { /* ... */ }
impl ContextQueryBuilder {
pub fn new() -> Self;
pub fn with_connection(conn: Arc<SochConnection>) -> Self;
pub fn for_session(self, session: &str) -> Self;
pub fn for_agent(self, agent: &str) -> Self;
pub fn with_budget(self, tokens: usize) -> Self;
pub fn include_schema(self, include: bool) -> Self;
pub fn format(self, format: ContextFormat) -> Self;
pub fn truncation(self, strategy: TruncationStrategy) -> Self;
pub fn set_var(self, name: &str, value: ContextValue) -> Self;
pub fn section(self, name: &str, priority: i32) -> SectionBuilder;
pub fn build(self) -> ContextQuery;
pub fn execute(self) -> Result<ContextQueryResult, ContextQueryError>;
}

pub struct SectionBuilder {
/* get / last / search(collection, query_var, top_k) / select / where_eq / where_gt
/ where_lt / where_like / limit / min_score(f32) / summarize / project / done() */
}

pub enum ContextFormat { /* ... */ }
pub enum TruncationStrategy { /* ... */ }
pub enum ContextValue { /* ... */ }

pub struct ContextQuery {
pub fn execute(self) -> Result<ContextQueryResult, ContextQueryError>;
}
pub struct ContextQueryResult {
pub fn utilization(&self) -> f64;
// included_sections / dropped_sections / truncated_sections
}
pub enum ContextQueryError { /* ... */ }
Builder method names

The actual builder uses for_session / with_budget, not the older from_session / with_token_limit names that appear in some doc comments.

Graph overlay

The graph module (generic over C: ConnectionTrait) stores typed nodes and edges.

pub struct GraphOverlay<C: ConnectionTrait> { /* ... */ }
impl<C: ConnectionTrait> GraphOverlay<C> {
pub fn new(conn: Arc<C>, namespace: &str) -> Self;
pub fn add_node(/* ... */) -> Result<RecordId>;
pub fn get_node(&self, id: &RecordId) -> Result<Option<GraphNode>>;
pub fn update_node(/* ... */) -> Result<()>;
pub fn delete_node(&self, id: &RecordId, cascade: bool) -> Result<()>;
pub fn node_exists(&self, id: &RecordId) -> Result<bool>;

pub fn add_edge(/* ... */) -> Result<()>;
pub fn get_edges(&self, from: &RecordId, edge_type: Option<&str>) -> Result<Vec<GraphEdge>>;
pub fn get_incoming_edges(/* ... */) -> Result<Vec<GraphEdge>>;
pub fn delete_edge(/* ... */) -> Result<()>;

pub fn bfs(/* ... */) -> Result<Vec<RecordId>>;
pub fn dfs(/* ... */) -> Result<Vec<RecordId>>;
pub fn shortest_path(/* ... */) -> Result<Option<Vec<RecordId>>>;
pub fn get_neighbors(/* ... */) -> Result<Vec<Neighbor>>;
pub fn get_nodes_by_type(&self, node_type: &str, limit: usize) -> Result<Vec<GraphNode>>;
pub fn get_subgraph(/* ... */) -> Result<Subgraph>;
}

pub enum TraversalOrder { BFS, DFS }
pub enum EdgeDirection { Outgoing, Incoming, Both }
pub struct GraphNode { pub id: RecordId, pub node_type: String, pub properties: HashMap<String, SochValue> }
pub struct GraphEdge { pub from_id: RecordId, pub edge_type: String, pub to_id: RecordId, pub properties: HashMap<String, SochValue> }
pub struct Neighbor { pub node_id: RecordId, pub edge: GraphEdge }
pub struct Subgraph { pub nodes: Vec<GraphNode>, pub edges: Vec<GraphEdge> }

Temporal graph

The temporal_graph module adds bitemporal (time-versioned) edges.

pub type Timestamp = u64;

pub struct TemporalGraphOverlay<C: ConnectionTrait> { /* ... */ }
impl<C: ConnectionTrait> TemporalGraphOverlay<C> {
pub fn new(conn: Arc<C>, namespace: &str) -> Self;
pub fn with_bucket_granularity(self, bucket: TimeBucket) -> Self;

pub fn add_edge(/* ... */) -> Result<()>;
pub fn add_edge_at(/* ..., t: Timestamp */) -> Result<()>;
pub fn invalidate_edge(/* ... */) -> Result<()>;
pub fn invalidate_edge_at(/* ..., t: Timestamp */) -> Result<()>;

pub fn get_edges_at(/* ..., t: Timestamp */) -> Result<Vec<TemporalEdge>>;
pub fn get_edges_in_window(/* start, end */) -> Result<Vec<TemporalEdge>>;
pub fn neighbors_at(/* ... */) -> Result<Vec<RecordId>>;
pub fn subgraph_at(/* ... */) -> Result<TemporalSubgraph>;
pub fn edge_history(/* ... */) -> Result<Vec<TemporalEdge>>;
}

pub struct TimeInterval { /* from / between / now / contains / overlaps / is_active / close_at / duration_ms */ }
pub struct TemporalEdge { pub fn is_valid_at(&self, t: Timestamp) -> bool; pub fn is_active(&self) -> bool; }
pub struct TemporalQuery { /* at(t) / window(start, end) / now() / with_history() */ }
pub enum TimeBucket { /* bucket_key(t) -> u64 */ }
pub struct TemporalSubgraph { /* ... */ }

Policy engine

The policy module (generic over C: ConnectionTrait) intercepts reads/writes/deletes and enforces rate limits and audit logging.

pub struct PolicyEngine<C: ConnectionTrait> { /* ... */ }
impl<C: ConnectionTrait> PolicyEngine<C> {
pub fn new(conn: Arc<C>) -> Self;
pub fn before_write(self, pattern: &str, handler: PolicyHandler) -> Self;
pub fn after_write(self, pattern: &str, handler: PolicyHandler) -> Self;
pub fn before_read(self, pattern: &str, handler: PolicyHandler) -> Self;
pub fn after_read(self, pattern: &str, handler: PolicyHandler) -> Self;
pub fn before_delete(self, pattern: &str, handler: PolicyHandler) -> Self;
pub fn add_rate_limit(self, operation: &str, max_per_minute: u32, scope: /* Scope */) -> Self;
pub fn enable_audit(self) -> Self;
pub fn disable_audit(self) -> Self;
pub fn get_audit_log(&self, limit: usize) -> Vec<AuditEntry>;

pub fn put(/* ... */) -> Result<()>;
pub fn get(/* ... */) -> Result<Option<Vec<u8>>>;
pub fn delete(/* ... */) -> Result<()>;
}

pub enum PolicyAction { /* ... */ }
pub enum PolicyTrigger { /* ... */ }
pub enum PolicyOutcome { /* ... */ }

pub struct PolicyContext { /* new(operation, key) / get / set / with_agent_id / with_session_id */ }
pub type PolicyHandler = Arc<dyn Fn(&PolicyContext) -> PolicyAction + Send + Sync>;

pub struct CompiledPolicySet {
pub fn new() -> Self;
pub fn add_rule(self, rule: PolicyRule, handler: Option<PolicyHandler>) -> Self;
pub fn evaluate(&self, trigger: PolicyTrigger, ctx: &PolicyContext) -> EvaluationResult;
}
pub struct PolicyRule { /* ... */ }
pub struct EvaluationResult {
pub fn is_allowed(&self) -> bool;
pub fn get_modification(&self) -> Option<Vec<u8>>;
}
pub struct AuditEntry { /* ... */ }
pub struct PolicyViolationError { /* ... */ }

Helpers: deny_all(), allow_all(), require_agent_id(), redact_value(Vec<u8>).

Tool routing

The routing module (generic over C: ConnectionTrait) registers agents and tools and routes calls between them.

pub struct AgentRegistry<C> {
/* new(Arc<C>) / register_agent / unregister_agent / get_agent / list_agents
/ find_capable_agents / update_agent_status / record_call */
}
pub struct ToolRouter<C> {
/* new(Arc<AgentRegistry<C>>, Arc<C>) / with_default_strategy / register_tool(Tool)
/ unregister_tool / get_tool / list_tools / route(...) */
}
pub struct ToolDispatcher<C> {
/* new(conn) / registry() / router() / register_local_agent / register_remote_agent
/ register_tool / invoke(...) / list_agents / list_tools */
}

pub enum ToolCategory { /* ... */ }
pub enum RoutingStrategy { /* ... */ }
pub enum AgentStatus { /* ... */ }

pub struct Tool { /* ... */ }
pub struct Agent { /* ... */ }
pub struct AgentConfig { /* with_endpoint / with_handler / priority */ }
pub struct RouteResult { /* ... */ }
pub struct RoutingContext { /* new / with_session_id / with_preferred_agent / exclude_agent */ }
pub type ToolHandler = /* ... */;

Priority queue

The queue module provides a durable, visibility-timeout priority queue (re-exported in the prelude).

pub struct PriorityQueue { /* ... */ }
impl PriorityQueue {
pub fn new(config: QueueConfig) -> Self;
pub fn queue_id(&self) -> &str;
pub fn enqueue(&self, priority: i64, payload: Vec<u8>) -> Result<QueueKey>;
pub fn enqueue_delayed(&self, /* ... */) -> Result<QueueKey>;
pub fn dequeue(&self, worker_id: &str) -> Result<DequeueResult>;
pub fn dequeue_with_timeout(&self, /* ... */) -> Result<DequeueResult>;
pub fn ack(&self, task_id: /* ... */) -> Result<()>;
pub fn nack(&self, /* ... */) -> Result<()>;
pub fn extend_visibility(&self, task_id: /* ... */, additional_ms: u64) -> Result<()>;
pub fn stats(&self) -> QueueStats;
}

pub struct QueueConfig {
pub queue_id: String,
pub default_visibility_timeout_ms: u64, // default 30_000
pub max_attempts: u32, // default 3
pub ascending_priority: bool, // default true
pub dead_letter_queue_id: Option<String>, // default None
}
// builders: with_visibility_timeout / with_max_attempts / with_ascending_priority / with_dead_letter_queue

pub struct Task { /* new(QueueKey, payload) / with_max_attempts / is_visible / should_dead_letter */ }
pub enum TaskState { /* ... */ }
pub enum DequeueResult { /* ... */ }
pub struct QueueStats { /* ... */ }
pub struct QueueKey { /* ... */ }
pub struct Claim { /* ... */ }

Semantic cache

The semantic_cache module (generic over C: ConnectionTrait) caches query results keyed by query text and an allowed-set hash, with optional similarity matching.

pub struct SemanticCache<C> { /* ... */ }
impl<C: ConnectionTrait> SemanticCache<C> {
pub fn new(conn: Arc<C>) -> Self;
pub fn with_config(conn: Arc<C>, config: SemanticCacheConfig) -> Self;
pub fn lookup(&self, /* ... */) -> Result<CacheLookupResult>;
pub fn store(&self, /* ... */) -> Result<()>;
pub fn delete(&self, key: &CacheKey) -> Result<bool>;
pub fn invalidate_by_source(&self, doc_id: &str) -> Result<usize>;
pub fn get_provenance(&self, key: &CacheKey) -> Result<Vec<String>>;
pub fn cleanup_expired(&self) -> Result<usize>;
}

pub struct SemanticCacheConfig {
pub default_ttl: Duration, // default 3600s (1h)
pub similarity_threshold: f32, // default 0.95
pub max_entries: usize, // default 10_000
pub enable_semantic_search: bool, // default true
pub track_hits: bool, // default true
}

pub struct CacheKey { /* new(query, namespace, allowed_set_hash: u64) / to_storage_key() -> Vec<u8> */ }
pub struct CacheEntry { /* ... */ }
pub enum CacheMatchType { /* is_hit / is_exact */ }
pub struct CacheLookupResult { pub fn is_hit(&self) -> bool; pub fn result(&self) -> Option<&[u8]>; }

pub fn hash_allowed_set<'a>(ids: impl Iterator<Item = &'a u64>) -> u64;

Atomic memory

The atomic_memory module (generic over C: ConnectionTrait) writes a memory unit (blob + embeddings + graph nodes/edges) atomically with crash recovery.

pub struct AtomicMemoryWriter<C> { /* ... */ }
impl<C: ConnectionTrait> AtomicMemoryWriter<C> {
pub fn new(conn: Arc<C>) -> Self;
pub fn write_atomic(&self, /* ... */) -> Result<AtomicWriteResult>;
pub fn recover(&self) -> Result<RecoveryReport>;
pub fn cleanup(&self, max_age_secs: u64) -> Result<usize>;
}

pub struct MemoryWriteBuilder {
/* new(memory_id) / put_blob / put_embedding / put_embedding_with_meta
/ create_node / create_node_with_props / create_edge / create_edge_with_props
/ execute<C: ConnectionTrait>(...) / ops() -> &[MemoryOp] */
}

pub enum MemoryOp { /* ... */ }
pub enum IntentStatus { /* ... */ }
pub struct MemoryIntent { /* ... */ }
pub struct AtomicWriteResult { /* ... */ }
pub struct RecoveryReport { /* ... */ }

Batch writer and schema

// batch module
pub struct BatchWriter<'a> {
/* new(conn) / max_batch_size / auto_commit(bool) / insert(table, Vec<(&str, SochValue)>)
/ insert_slice(...) / update(...) / delete(table, key_field, SochValue)
/ pending_count / total_count / execute() -> BatchResult */
}
pub enum BatchOp { /* ... */ }
pub struct BatchResult { /* ... */ }

// schema module
pub struct SchemaBuilder {
/* table(name) / field(name, SochType) -> FieldConfig / primary_key(field)
/ index(name, &[&str], unique: bool) / build() -> SochSchema / get_fields() */
}
pub struct FieldConfig {
/* not_null / unique / default_value(&str) / field(...) / primary_key(...) / index(...) / build() */
}
pub struct TableDescription { /* ... */ }
pub struct ColumnDescription { /* ... */ }

// connection methods
conn.create_table(schema: SochSchema) -> Result<CreateTableResult>;
conn.drop_table(name: &str) -> Result<()>;
conn.create_index(/* ... */) -> Result<()>;
conn.drop_index(/* ... */) -> Result<()>;
Deprecated

GroupCommitBuffer and GroupCommitConfig (in the batch module) are deprecated but still re-exported for backwards compatibility.

Error handling

All fallible operations return sochdb::Result<T>, which uses ClientError.

pub type Result<T> = std::result::Result<T, ClientError>;

pub enum ClientError {
PathNotFound(String),
ScalarPath(String),
Schema(String),
Validation(String),
NotFound(String),
Transaction(String),
SerializationFailure { our_txn: u64, conflicting_txn: u64, conflicting_key: Vec<u8> },
Visibility(String),
Wal(String),
Storage(String),
Io(std::io::Error),
Serialization(String),
Parse(String),
Constraint(String),
Vector(String),
PqNotTrained,
TypeMismatch { expected: String, actual: String },
TokenBudgetExceeded { used: usize, budget: usize },
PoolExhausted,
Query(String),
Internal(String),
}

ClientError derives thiserror::Error and implements From<std::io::Error> and From<bincode::Error> (mapped to Serialization).

note

There is no sochdb::Error type and no ConnectionFailed variant — older README snippets that reference those are stale. Use ClientError.

High-level facade: SochClient

SochClient wraps an in-memory SochConnection and offers a single entry point for queries, vectors, transactions, and SQL.

pub struct SochClient { /* wraps Arc<SochConnection> */ }
impl SochClient {
pub fn open(path: impl AsRef<Path>) -> Result<Self>;
pub fn open_with_config(path: impl AsRef<Path>, config: ClientConfig) -> Result<Self>;
pub fn with_token_budget(self, budget: usize) -> Self;

pub fn query(&self, path: &str) -> PathQuery<'_>;
pub fn vectors(&self, name: &str) -> Result<VectorCollection>;
pub fn begin(&self) -> Result<ClientTransaction<'_>>; // snapshot isolation
pub fn begin_with_isolation(&self, level: IsolationLevel) -> Result<ClientTransaction<'_>>;
pub fn snapshot(&self) -> Result<SnapshotReader<'_>>;
pub fn execute(&self, sql: &str) -> Result<QueryResult>; // delegates to query_ast
pub fn connection(&self) -> &SochConnection;
pub fn stats(&self) -> ClientStats;
}

pub struct ClientConfig {
pub token_budget: Option<usize>, // default None
pub streaming: bool, // default false
pub output_format: OutputFormat, // default Soch (TOON)
pub pool_size: usize, // default 10
}
pub enum OutputFormat { Soch, Json, Columnar }

pub struct ClientStats {
pub queries_executed: u64,
pub soch_tokens_emitted: u64,
pub json_tokens_equivalent: u64,
pub token_savings_percent: f64,
pub cache_hit_rate: f64,
}
Durability of SochClient

SochClient is backed by the in-memory SochConnection. For durable storage use Connection / DurableConnection directly, or DurableSochClient (requires the embedded feature).

With the embedded feature, DurableSochClient offers a durable equivalent:

#[cfg(feature = "embedded")]
pub struct DurableSochClient { /* open / from_connection / open_with_config
/ begin / commit / abort / put / get / delete / scan / fsync / stats */ }

Prelude

For convenience, import the common types at once:

use sochdb::prelude::*;
// brings in: Connection, DurableConnection, InMemoryConnection, SochClient,
// PathQuery, CompareOp, queue types, ClientError, and
// sochdb_core::soch::{SochType, SochValue}

See also