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
NOTICEfile. 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)
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
| Feature | Default | Effect |
|---|---|---|
default | — | No features enabled. |
simd | off | SIMD-accelerated distance kernels. |
embedded | off | Enables EmbeddedConnection / DurableSochClient, which drive the full Database kernel directly (SQL via execute_sql, etc.). |
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;
| Type | Alias(es) | Backing | Use for |
|---|---|---|---|
DurableConnection | Connection, Database | WAL + MVCC + crash recovery | Production durable storage. |
SochConnection | InMemoryConnection | In-memory | Tests, and SQL execution (execute_sql/query_sql). |
EmbeddedConnection | — | Full Database kernel | Direct kernel access; requires the embedded feature. |
ReadOnlyConnection | — | Read-only handle | Snapshot/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:
| Preset | sync_mode | ordered index | batch / max wait |
|---|---|---|---|
throughput_optimized() | Normal | off | 1000 / 50_000 us |
latency_optimized() | Full | on | 10 / 1_000 us |
max_durability() | Full (no group commit) | on | 1 / 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"));
}
}
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.
Vector search
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);
}
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 { /* ... */ }
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<()>;
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).
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,
}
SochClientSochClient 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}