Luis Tavarez · Noticias

CedroDB CLI: una orden y su evento en una transacción

Un ejemplo ejecutable de arquitectura outbox con la CLI de CedroDB 0.8.0: validación, lote atómico y verificación.

Luis Tavarez ·

El problema: dos escrituras relacionadas

Una orden confirmada y el evento que anuncia su confirmación deben persistir juntos. Guardarlos por separado permite que una operación falle después de guardar la otra.

Recorrido de arquitectura

CLI CedroDB → validación Python → transacción del motor Rust → colecciones orders y outbox en el mismo log.

El comando batch aplica las dos escrituras como un lote atómico. La colección outbox conserva el trabajo pendiente. Un consumidor separado puede leerlo y entregar el evento; este ejemplo no implementa ese consumidor.

Ejecutar el ejemplo

Instala cedrodb==0.8.0 con pip y ejecuta este archivo con Python 3.9 o superior. Utiliza un directorio temporal y no modifica tus bases existentes.

python
import json
import subprocess
import sys
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as directory:
    database = str(Path(directory) / "orders")

    def cli(*arguments, payload=None):
        command = [sys.executable, "-m", "cedrodb", *arguments,
                   "--db", database, "--json"]
        if payload is not None:
            command.append("--stdin")
        result = subprocess.run(command, input=json.dumps(payload) if payload is not None else None,
                                text=True, capture_output=True, check=True)
        return json.loads(result.stdout)

    cli("init")
    cli("batch", payload=[
        {"kind": "put", "collection": "orders", "key": "order-001",
         "value": {"status": "confirmed"}},
        {"kind": "put", "collection": "outbox", "key": "order-001",
         "value": {"event": "order.confirmed", "delivered": False}},
    ])
    assert cli("get", "orders", "order-001")["value"]["status"] == "confirmed"
    assert cli("get", "outbox", "order-001")["found"] is True
    assert cli("verify")["records"] == 2
    print("OK: order and outbox persisted atomically")

Qué comprueba

Las aserciones leen la orden y su evento y verifican los dos registros del log. El resultado esperado es OK: order and outbox persisted atomically.

Límites que debes diseñar

La transacción local no hace atómica una llamada a un servicio externo. Para producción, define reintentos, claves de idempotencia, deduplicación y cuándo marcar el evento como entregado. Una prueba de éxito tampoco sustituye las pruebas de recuperación ante fallos.

Arquitectura en práctica

Una orden y su evento, en la misma transacción

Un ejemplo complementario del portafolio: sigue el recorrido de la CLI hasta el log y ejecuta el código con CedroDB 0.8.0.

Recorrido de escritura

LT Architecture StudioDiagrama creado con nuestra herramienta. Explóralo y adáptalo a tu proyecto.
Arquitectura de CedroDB: CLI, SDK Python y motor Rust con orders y outbox en una transacción local
  1. CLI CedroDB
  2. Validación Python
  3. Transacción Rust
  4. orders + outbox

La orden y el evento se guardan juntos. La entrega externa y su deduplicación siguen siendo responsabilidad del consumidor.

Código reproducible

Instala cedrodb==0.8.0 y ejecuta este archivo con Python 3.9 o superior. El ejemplo usa una base temporal.

python
import json
import subprocess
import sys
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as directory:
    database = str(Path(directory) / "orders")

    def cli(*arguments, payload=None):
        command = [sys.executable, "-m", "cedrodb", *arguments,
                   "--db", database, "--json"]
        if payload is not None:
            command.append("--stdin")
        result = subprocess.run(command, input=json.dumps(payload) if payload is not None else None,
                                text=True, capture_output=True, check=True)
        return json.loads(result.stdout)

    cli("init")
    cli("batch", payload=[
        {"kind": "put", "collection": "orders", "key": "order-001",
         "value": {"status": "confirmed"}},
        {"kind": "put", "collection": "outbox", "key": "order-001",
         "value": {"event": "order.confirmed", "delivered": False}},
    ])
    assert cli("get", "orders", "order-001")["value"]["status"] == "confirmed"
    assert cli("get", "outbox", "order-001")["found"] is True
    assert cli("verify")["records"] == 2
    print("OK: order and outbox persisted atomically")

Resultado esperado: OK: order and outbox persisted atomically

Leer la guía completa

Este ejemplo es independiente del contenido de la noticia y no atribuye esta arquitectura a terceros.