Embedded (Rust)
El crate fachada namidb es la API paraguas estable. Re-exporta los
tipos que vas a tocar más seguido de namidb-core, namidb-storage,
namidb-graph y namidb-query, así que el código aguas abajo solo
necesita una línea en Cargo.toml.
Agregar la dependencia
[dependencies]namidb = "0.4"tokio = { version = "1", features = ["full"] }object_store = "0.13"anyhow = "1"También dependes directamente de
object_store porque ese es el trait que
toma la capa de almacenamiento — elegir un backend (S3, GCS, Azure, disco
local, memoria) es instanciar un object_store.
Ejemplo mínimo
use std::sync::Arc;
use namidb::core::id::NamespaceId;use namidb::query::{execute, lower, parse, Params};use namidb::storage::{NamespacePaths, WriterSession};use object_store::{memory::InMemory, ObjectStore};
#[tokio::main]async fn main() -> anyhow::Result<()> { // 1. Elige un backend. `InMemory` para el demo; en producción usas // object_store::aws::AmazonS3, GoogleCloudStorage, etc. let store: Arc<dyn ObjectStore> = Arc::new(InMemory::new());
// 2. Resuelve el layout en el bucket para un namespace. let paths = NamespacePaths::new("tenants", NamespaceId::new("demo")?);
// 3. Abre un writer para el namespace (un solo writer por namespace). let mut writer = WriterSession::open(store, paths).await?;
// ... upsert de nodos / edges, después commit_batch + flush ...
// 4. Fija un snapshot de lectura, parsea, baja y ejecuta una consulta. let snap = writer.snapshot(); let q = parse("MATCH (a:Person) RETURN count(*) AS n")?; let plan = lower(&q)?; let rows = execute(&plan, &snap, &Params::new()).await?;
println!("{rows:?}"); Ok(())}Forma de la API
El crate paraguas namidb re-exporta cuatro namespaces. Los ítems más
usados por namespace:
| Re-export | Lo que obtienes |
|---|---|
namidb::core | id::NamespaceId, runtime values, tipos de schema |
namidb::storage | WriterSession, Snapshot, NamespacePaths, parser de URI |
namidb::graph | columnas de propiedades + adyacencia CSR (helpers de lectura) |
namidb::query | parse, lower, execute, Params, LogicalPlan |
La lista completa de re-exports está en crates/namidb/src/lib.rs. Los
crates individuales siguen en crates.io si necesitas una superficie de
dependencias más ajustada, pero enlazar solo contra namidb es la ruta
soportada.
Aperturas estilo URI
Si prefieres manejar el writer desde una URI string (la misma forma que
usan el cliente Python, la CLI y el servidor), usa el helper
parse_uri del crate de storage en vez de construir el ObjectStore
a mano:
use namidb::storage::{parse_uri, WriterSession};
let (store, paths) = parse_uri("s3://my-bucket/data?ns=prod®ion=us-east-1")?;let mut writer = WriterSession::open(store, paths).await?;Todos los esquemas de URI documentados en Backends de almacenamiento funcionan aquí.
Camino de escritura
El WriterSession es dueño de las mutaciones en stage. Dos formas de
escribir:
- Escrituras Cypher vía
execute_write—CREATE,MERGE,SET,DELETE,REMOVE. Auto-commit al final de cada statement. - API de staging tipada —
writer.upsert_node,writer.upsert_edge,writer.tombstone_node,writer.tombstone_edge. Acumulas las mutaciones que quieras y llamaswriter.commit_batch().awaitpara hacerlas persistentes (WAL append + manifest CAS), despuéswriter.flush().awaitpara empujar el memtable a SSTs L0.
La superficie de la API de staging está en
crates/namidb-storage/src/lib.rs.
Single-writer-per-namespace
Dos procesos pueden abrir WriterSession::open(...) contra el mismo
namespace. El primero que emita un commit_batch gana; commits
posteriores desde una época vieja se rechazan vía manifest CAS
(If-Match en object stores, flock + rename atómico en file://).
Sin servicio externo de locks.
El namespace actual queda completamente descrito por la URI del bucket
más el nombre del namespace, así que los backups son aws s3 sync y un
tenant es una carpeta.
Siguientes pasos
- Leer datos — cláusulas de lectura en Cypher.
- Escribir datos — cláusulas de escritura y el modelo de auto-commit.
- Librería Rust — la superficie pública completa en Rust.
- Backends de almacenamiento — gramática de URI por backend.