API HTTP (namidb-server)
namidb-server es un único binario de Rust (también publicado como
imagen de Docker) que abre un namespace y lo expone sobre HTTP. Mismo
motor que la librería embebida — lo único que agrega este binario es el
borde HTTP, autenticación con bearer token y un loop de flush periódico.
Instalar
cargo install --path crates/namidb-serverdocker build -t namidb-server:0.3 \ -f crates/namidb-server/Dockerfile .Ejecutar
namidb-server \ --store 's3://my-bucket?ns=prod®ion=us-east-1' \ --listen 0.0.0.0:8080 \ --auth-token "$NAMIDB_AUTH_TOKEN" \ --flush-interval 30sCada flag es también una env var: NAMIDB_STORE, NAMIDB_LISTEN,
NAMIDB_AUTH_TOKEN, NAMIDB_FLUSH_INTERVAL.
Endpoints (v0)
| Método | Path | Auth | Descripción |
|---|---|---|---|
GET | /v0/health | público | Liveness + versión de manifest + epoch |
GET | /v0/version | público | Versión de build del servidor |
POST | /v0/cypher | bearer | Ejecutar una query Cypher (lectura o escritura) |
POST | /v0/admin/flush | bearer | Forzar flush de memtable → SST L0 |
POST /v0/cypher
Request
{ "query": "MATCH (p:Person) WHERE p.age >= $min RETURN p.name AS name", "params": {"min": 18}}Response — lectura
{ "columns": ["name"], "rows": [{"name": "Alice"}, {"name": "Bob"}]}Response — escritura
{ "columns": ["a"], "rows": [{"a": {"_kind": "node", "id": "…", "label": "Person", "properties": {}}}], "write_outcome": { "nodes_created": 1, "edges_created": 0, "nodes_deleted": 0, "edges_deleted": 0, "properties_set": 0 }}Round-trip con curl
TOKEN=$(openssl rand -hex 32)
namidb-server --store memory://demo --listen 127.0.0.1:8080 --auth-token "$TOKEN" &
curl -s http://127.0.0.1:8080/v0/health | jq .
curl -s -X POST http://127.0.0.1:8080/v0/cypher \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"query": "CREATE (a:Person {name: \"Alice\", age: 30}) RETURN a.name AS name"}' \ | jq .
curl -s -X POST http://127.0.0.1:8080/v0/cypher \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"query": "MATCH (p:Person) RETURN p.name AS name, p.age AS age"}' \ | jq .Mapeo de tipos (JSON ↔ Cypher)
RuntimeValue de Cypher | JSON |
|---|---|
Null | null |
Bool | true / false |
Integer | number (i64) |
Float | number (f64) |
String | string |
Bytes | string base64 |
Vector(f32) | array de números |
List | array |
Map | object |
Date | string de fecha ISO-8601 |
DateTime (UTC µs) | string de timestamp RFC-3339 |
Node | {"_kind": "node", "id", "label", "properties"} |
Rel | {"_kind": "rel", "edge_type", "src", "dst", "properties"} |
Path | array alternando objetos de node/rel |
Modelo de concurrencia
namidb-server abre una WriterSession por proceso y serializa cada
request detrás de un Mutex de tokio. Esto es el invariante
single-writer-per-namespace de
RFC-001 elevado a la capa de
request: a lo sumo una sentencia de Cypher está en vuelo contra el
namespace a la vez. La latencia de lectura se mantiene predecible; el
throughput queda acotado por el mutador más lento.
Si necesitas escala horizontal de lectura hoy, apunta múltiples procesos
de namidb-server a la misma URI de --store: cada uno puede servir
lecturas desde la misma versión de manifest. A sólo uno se le va a
permitir commitear escrituras (al resto se los fencea vía CAS de epoch).
El fan-out concurrente de lecturas sin sostener el mutex del writer es trabajo de RFC-021.
Flush periódico
--flush-interval (default 30s) controla cada cuánto la tarea de
background convierte el memtable a SSTs L0. Ponelo en 0s para
deshabilitar el loop y llamar a POST /v0/admin/flush desde cron / un
sidecar en su lugar.
Roadmap
/v0/cypher/stream— response NDJSON con streaming para result sets grandes./v0/cypher/arrow— body Arrow IPC para ingesta zero-copy en DataFrame./v0/metrics— exposición Prometheus.- Compatibilidad con el protocolo Bolt — drivers en cualquier lenguaje que ya hable Neo4j hoy.