Documentos de Asset Core

Documentación del motor de estado mundial determinista y referencias de API.

Documentos de Decision Gate

Frescura y Repetición

La frescura describe cuán actuales son las proyecciones del daemon de lectura en relación con el registro de confirmaciones. La reproducción es el mecanismo que mantiene las proyecciones sincronizadas. Comprender ambos es esencial para operar Asset Core a gran escala sin sorpresas de obsolescencia.

Problema que este concepto resuelve

En los sistemas basados en eventos, las escrituras y lecturas están separadas:

  • El daemon de escritura compromete eventos de inmediato
  • El daemon de lectura debe procesar esos eventos para actualizar su vista

Esto crea una brecha de frescura: el tiempo entre cuando un commit es reconocido y cuando aparece en las consultas de lectura. Comprender esta brecha es esencial para:

  • Construyendo aplicaciones que necesitan lecturas consistentes
  • Diagnóstico de la aparente “obsolescencia” de los datos
  • Ajuste del rendimiento del sistema

Ideas principales

Registro de Commits

El registro de confirmaciones es la secuencia de lotes de eventos que solo se puede agregar. Es la única fuente utilizada para reconstruir proyecciones, por lo que define la línea de tiempo autoritativa. La durabilidad depende del backend: los registros en memoria son rápidos y desechables, mientras que los registros en archivo/segmentados persisten a través de reinicios. Este diseño (cubierto en Modelo de Ejecución) es lo que hace posibles las garantías de AssetCore.

  • Solo adición: Nuevos lotes se añaden al final (sin actualizaciones en el lugar, sin eliminaciones)
  • Inmutable: Una vez escrito, los lotes no cambian (no se pueden modificar ni reordenar)
  • Secuenciado: Cada lote tiene un número de secuencia monótono (orden total de todos los eventos)

El daemon de escritura añade entradas al registro; el daemon de lectura las sigue. Esta separación es crítica: el daemon de escritura nunca bloquea el rendimiento de lectura, y el daemon de lectura puede retrasarse sin afectar el rendimiento de escritura. Lo que se gana: escalado independiente de escritura y lectura, recuperación ante fallos al usar un backend de registro duradero, depuración forense al reproducir hasta cualquier punto. Lo que se cede: las lecturas son eventualmente consistentes, no inmediatamente consistentes; siempre hay algún retraso.

Proyecciones

Las proyecciones son vistas en memoria del estado. Están optimizadas para consultas y siempre se pueden reconstruir a partir del registro, por lo que la reproducción es una invariante central. Esta separación entre “fuente de verdad” (registro de confirmaciones) y “interfaz de consulta” (proyecciones) es fundamental para la arquitectura de AssetCore.

  • Construido aplicando eventos del registro de confirmaciones (proceso de reproducción, ver más abajo)
  • Optimizado para el rendimiento de consultas (indexado, desnormalizado para búsquedas rápidas)
  • Publicado de manera atómica a través del intercambio de instantáneas (sin actualizaciones parciales visibles para las consultas)

Las proyecciones son datos derivados. Si se pierden, se pueden reconstruir a partir del registro de confirmaciones. Esta propiedad es lo que hace que AssetCore sea operativamente simple: siempre puedes reconstruir el estado de la consulta a partir del registro, y la durabilidad es una elección de implementación. Sin esto, perder un daemon de lectura significaría pérdida de datos o protocolos de replicación complejos. Con esto, perder un daemon de lectura es inconveniente (tiempo de reconstrucción) pero no catastrófico.

Lo que ganas: estado de consulta desechable (reconstruir a voluntad), libertad para cambiar la estructura de proyección (repetir con nueva lógica), confianza en que la analítica/notificaciones nunca se desvían del estado operativo (todos consumen el mismo registro). Lo que cedes: el tiempo de reconstrucción después de fallos escala con el tamaño del registro, aunque los puntos de control hacen que esto sea manejable.

Puntos de control

Los puntos de control registran el progreso a través del registro de confirmaciones. Hacen que la recuperación sea rápida y permiten razonar sobre exactamente cuánta información de estado se ha aplicado. Sin puntos de control, cada reinicio requeriría reproducir todo el registro desde el principio, lo cual es factible para sistemas pequeños, pero catastrófico para cargas de trabajo en producción con millones de eventos.

  • Escritura de daemon: Rastrea la última secuencia comprometida (para saber dónde reanudar después de un fallo)
  • Daemon de lectura: Rastrea la última secuencia aplicada (para que pueda reanudar la reproducción sin volver a aplicar eventos)

Los puntos de control permiten:

  • Inicio rápido: Reanudar desde el punto de control, no desde el principio (reproduciendo 1,000 eventos en lugar de 1,000,000)
  • Recuperación de fallos: Repetir desde la posición de punto de control hacia adelante (ver Modelo de Ejecución)
  • Cálculo de frescura: Comparar marcas de agua de secuencia mundial (retraso = commit_log_seq - projection_seq)

Lo que ganas: tiempo de inicio medido en segundos, no en horas, ventanas de recuperación predecibles, monitoreo de frescura en tiempo real. Lo que cedes: sobrecarga de puntos de control (escrituras de instantáneas periódicas), aunque estas son ligeras y configurables.

Metadatos de Frescura

Las respuestas de lectura incluyen información de frescura; los clientes pueden pasar x-assetcore-min-world-seq para bloquear hasta una secuencia mínima. Así es como se aplica la lectura de sus escrituras y la consistencia estricta en el límite del cliente. Sin un seguimiento explícito de frescura, no tendrías idea de si una consulta devolvió datos obsoletos o datos frescos; la depuración se convierte en un juego de adivinanzas.

{
  "freshness": {
    "namespace": 1,
    "world_seq": 42,
    "commit_log_world_seq": 45,
    "lag": 3,
    "lag_ms": 125
  }
}
  • world_seq: La última secuencia aplicada a la proyección de lectura (lo que ven las consultas)
  • commit_log_world_seq: La última secuencia de registro de confirmaciones observada (lo que se ha confirmado)
  • lag: La diferencia en los commits (cuántos lotes están atrasados)
  • lag_ms: La diferencia de tiempo en milisegundos (cuán antiguo es el dato)

La diferencia es el lag: cuántos commits aún no se han aplicado (y cuánto tiempo dura esa brecha en milisegundos). Este lag es normal y esperado en sistemas basados en eventos; es el costo de la separación de escritura/lectura. La parte crítica es que está medido y expuesto, no oculto.

Lo que ganas: visibilidad sobre la obsolescencia (saber cuándo los datos son recientes), capacidad para hacer cumplir la consistencia (bloquear lecturas hasta que sean lo suficientemente recientes), información para depuración (correlacionar problemas de consulta con picos de retraso). Lo que cedes: cargas de respuesta ligeramente más grandes (metadatos de frescura en cada lectura), pero el valor operativo lo compensa.

Proceso de Repetición

El replay es el mecanismo que mantiene las proyecciones sincronizadas con el registro de confirmaciones. No es solo una función de recuperación; es el bucle operativo central para el daemon de lectura. Entender el replay es entender cómo funciona AssetCore.

Cuando el daemon de lectura sigue el registro de confirmaciones:

  1. Obtener el siguiente lote después del punto de control (desde el almacenamiento del registro de confirmaciones)
  2. Aplicar cada evento a través de los setters de L1 (ver Modelo de Ejecución para detalles de la capa)
  3. Actualizar punto de control (registrar progreso)
  4. Publicar nueva instantánea (intercambio atómico, sin actualizaciones parciales visibles)

Los eventos son idempotentes: aplicar el mismo evento dos veces produce el mismo estado. Esto hace que la repetición sea segura para reintentar y es lo que permite la recuperación determinista después de fallos parciales. Más importante aún, significa que la repetición no es frágil: si no estás seguro de si se aplicó un evento, simplemente aplícalo de nuevo.

Por qué la reproducción es una característica clave: No se trata solo de la recuperación de fallos. Es depuración de viaje en el tiempo (reproduce hasta las 3:47 PM del martes e inspecciona el estado exacto), simulación (reproduce eventos de producción contra lógica experimental), análisis (reproduce el registro en una estructura de proyección diferente) y pruebas (verifica el comportamiento contra flujos de eventos reales). Los sistemas sin reproducción determinista no pueden hacer nada de esto de manera confiable.

Flujo de Recuperación

Después de un fallo, AssetCore se recupera automáticamente sin intervención manual. Esta es una de las propiedades más valiosas operativamente de la arquitectura: no hay páginas a las 3 AM para restaurar el estado manualmente.

Después de un fallo:

  1. Cargar el punto de control desde el disco (instantánea del último estado conocido como bueno)
  2. Recuperar eventos desde la posición del punto de control (solo eventos que aún no se han aplicado)
  3. Repetir eventos para reconstruir el estado (a través de los setters de L1, rápido y determinista)
  4. Reanudar el bucle de cola normal (volver a la operación en estado estable)

Porque los eventos llevan un estado posterior (ver Modelo de Ejecución), la reproducción no necesita volver a ejecutar la lógica de negocio. Simplemente establece los valores finales, eliminando la no determinación durante la recuperación. Esto es lo que hace que la recuperación sea rápida (sin sobrecarga de validación) y confiable (sin posibilidad de divergencia).

Lo que ganas: recuperación automática (sin pasos manuales), tiempo de recuperación predecible (escalado con eventos desde el punto de control), confianza en que el estado recuperado es idéntico en bytes al estado anterior al fallo. Lo que cedes: la recuperación no es instantánea; toma un tiempo proporcional al intervalo de punto de control, pero esto suele ser segundos, no minutos.

Cómo encaja en el sistema

Escribir Ruta

Client → Write Daemon → Commit Log
                         ↓
              [checkpoint updated]

El daemon de escritura actualiza su punto de control después de una persistencia exitosa.

Leer Ruta

Commit Log → Read Daemon → Projections → Client
    ↓
[checkpoint updated after apply]

El daemon de lectura publica instantáneas antes de actualizar su punto de control. Esto asegura:

  • Las consultas siempre ven un estado consistente
  • Los fallos no pierden el trabajo aplicado pero no registrado.

Informe de Frescura

El endpoint de salud de lectura informa sobre el retraso para un espacio de nombres:

{
  "status": "ready",
  "freshness": {
    "namespace": 1,
    "world_seq": 98,
    "commit_log_world_seq": 100,
    "lag": 2,
    "lag_ms": 250
  }
}

Monitore esto para detectar:

  • Funcionamiento normal (retraso cerca de 0)
  • Aumento temporal (picos de latencia que luego se recuperan)
  • Problemas sistemáticos (el retraso crece continuamente)

Invariantes clave y garantías

Consistencia Eventual

Las proyecciones eventualmente reflejarán todos los eventos comprometidos:

  • El daemon de lectura sigue continuamente el registro
  • La latencia puede aumentar durante ráfagas, pero se recupera
  • Ningún evento comprometido es permanentemente invisible

Publicar-antes-del-punto-de-control

Las instantáneas se publican antes de que se actualicen los puntos de control:

  • Las consultas ven datos que están garantizados como aplicados
  • Los fallos no hacen que los datos “desaparezcan”
  • Recuperación de repeticiones desde el último punto seguro

Reproducción Determinista

La reproducción produce un estado idéntico:

  • Los eventos llevan valores post-estados
  • No hay lógica de negocio durante la reproducción
  • Mismos eventos → mismo estado

Seguridad del Punto de Control

Los puntos de control se persisten de manera atómica:

  • No se permiten escrituras parciales de puntos de control
  • La recuperación siempre encuentra un punto de control válido
  • El progreso nunca se pierde entre reinicios

Ver también