Servidor HTTP
El binario namidb-server abre un namespace de NamiDB y lo expone sobre
una API REST pequeña. Es el mismo motor que la librería
embedded; todo lo que agrega este
binario es el límite HTTP, autenticación por bearer token, un loop de
flush periódico, y un listener Bolt opcional.
Consulta Instalación
para el comando de instalación (cargo install --path crates/namidb-server) o la imagen Docker.
Ejecutar
namidb-server \ --store "s3://my-bucket/data?ns=prod®ion=us-east-1" \ --listen 0.0.0.0:8080 \ --auth-token "$NAMIDB_AUTH_TOKEN" \ --flush-interval 30sCada flag también se puede setear vía env vars (NAMIDB_STORE,
NAMIDB_LISTEN, NAMIDB_AUTH_TOKEN, NAMIDB_FLUSH_INTERVAL,
NAMIDB_BOLT_LISTEN). La URI de --store sigue la misma gramática que
el cliente Python y la CLI — consulta Backends de
almacenamiento.
Si no pasas --auth-token, el servidor arranca en modo sin
autenticación e imprime un warning ruidoso. No expongas ese puerto al
internet público.
Endpoints (v0)
| Método | Path | Auth | Descripción |
|---|---|---|---|
GET | /v0/health | público | Liveness + versión del manifest + epoch |
GET | /v0/version | público | Versión del build del servidor |
POST | /v0/cypher | bearer | Ejecuta una consulta Cypher (lectura o escritura) |
POST | /v0/admin/flush | bearer | Fuerza un flush del memtable a SSTs 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 end-to-end 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 .Concurrencia
namidb-server mantiene un WriterSession por proceso. Las escrituras
se serializan detrás del invariante single-writer-per-namespace
(RFC-001): a lo sumo un statement de escritura está en vuelo contra el
namespace a la vez. Las lecturas ya no toman el mutex del writer — una
snapshot cell (RFC-021) publica la última vista persistente, varios
lectores la comparten vía un Arc, y una escritura refresca la cell
después de cada commit_batch / flush. El test de integración
(crates/namidb-server/tests/concurrent_reads.rs) mide un fan-out de
~7x con 8 lectores en una máquina de 4 cores.
Si hoy necesitas escala horizontal, apunta varios procesos
namidb-server a la misma URI de --store. Cada uno sirve lecturas
desde la misma versión del manifest, y solo a uno se le permite hacer
commit de escrituras (los demás quedan fenced vía epoch CAS).
Flush periódico
--flush-interval (default 30s) controla cada cuánto la tarea en
background convierte el memtable en SSTs L0. Ponlo en 0s para
desactivar el loop y llamar POST /v0/admin/flush desde cron o un
sidecar.
Protocolo Bolt
Pasa --bolt-listen 0.0.0.0:7687 (o NAMIDB_BOLT_LISTEN) para
exponer un listener Bolt 4.4 / 5.0 / 5.4 al lado de la API HTTP.
Ambos protocolos comparten el mismo WriterSession, el mismo auth
token, y el mismo invariante single-writer-per-namespace.
namidb-server \ --store memory://demo \ --listen 0.0.0.0:8080 \ --bolt-listen 0.0.0.0:7687 \ --auth-token "$NAMIDB_AUTH_TOKEN"from neo4j import GraphDatabasedriver = GraphDatabase.driver("bolt://localhost:7687", auth=("namidb", "$NAMIDB_AUTH_TOKEN"))with driver.session() as s: s.run("CREATE (:Person {name: 'Alice'})") for r in s.run("MATCH (p:Person) RETURN p.name AS name"): print(r["name"])El usuario de Bolt es el string literal namidb; la contraseña es el
mismo bearer token. Consulta Bolt (drivers
Neo4j) para la matriz de drivers y
RFC-022
para el diseño wire-level.
En el roadmap
El README del servidor lista estos endpoints como planeados pero aún sin aterrizar:
/v0/cypher/stream— streaming NDJSON para result sets grandes./v0/cypher/arrow— body Arrow IPC para ingesta zero-copy en DataFrames./v0/metrics— exposición Prometheus (counters, histograma de latencia, tasas de hit del caché).
Siguientes pasos
- API HTTP — referencia del mapeo de tipos y detalles del envelope JSON.
- Bolt (drivers Neo4j) — matriz de compatibilidad de drivers y snippets.
- Docker + MinIO — un stack
local completo en un solo
docker-compose.yml. - Configuración — cada env var que el servidor lee al arrancar.