Framework Open Source

goes

Aggregates, Commands y Projections con seguridad de tipos, desde el prototipado hasta producción.

158 ·Apache-2.0· Go ·17 forks
goes Gopher
Scroll
Resumen

¿Qué es goes?

goes es un framework de Event Sourcing para Go que proporciona los componentes básicos para aplicaciones distribuidas basadas en eventos. Aggregates, Commands y Projections con seguridad de tipos, con backends intercambiables para cualquier nivel de escalabilidad.

A diferencia de muchas librerías de Event Sourcing que son demasiado académicas o demasiado opinionated, goes se basa en Go idiomático. Sin generación de código, sin annotations mágicas: solo interfaces, generics y composición. Defines tus Aggregates como structs de Go normales, registras controladores de eventos mediante funciones tipadas y el framework se encarga de la persistencia, la reproducción y la concurrencia.

goes está dirigido a equipos de Go que desean integrar Event Sourcing y CQRS en sistemas existentes o nuevos sin quedar vinculados a una configuración de infraestructura específica. Ya sea que comiences con un prototipo simple en memoria o ejecutes un sistema distribuido con NATS, MongoDB y PostgreSQL, la lógica de dominio permanece idéntica.

En acción
order.go
// Define your aggregate
type Order struct {
    *aggregate.Base

    Items  []LineItem
    Status OrderStatus
}

// Register typed event handlers
func NewOrder(id uuid.UUID) *Order {
    o := &Order{Base: aggregate.New("order", id)}

    event.ApplyWith(o, o.placed, "order.placed")
    event.ApplyWith(o, o.paid, "order.paid")

    return o
}

// Produce events from commands
func (o *Order) Place(items []LineItem) error {
    aggregate.Next(o, "order.placed",
        OrderPlaced{Items: items},
    )
    return nil
}

// Rebuild state from events
func (o *Order) placed(e event.Of[OrderPlaced]) {
    o.Items = e.Data().Items
    o.Status = Placed
}

Sin generación de código, sin annotations: solo interfaces de Go, generics y composición. La lógica de dominio se mantiene limpia y portable.

Motivación

¿Por qué Event Sourcing?

El problema

Los sistemas CRUD tradicionales solo almacenan el estado actual. Si se produce un error o se necesita una auditoría, falta el historial. Los datos se sobrescriben y se pierde el contexto. ¿Quién cambió qué, cuándo y por qué? Estas preguntas no pueden responderse con una sentencia UPDATE clásica.

El enfoque

Event Sourcing almacena cada cambio de estado como un evento. El estado actual se reconstruye a partir del historial de eventos. No se pierde nada: registros de auditoría completos, depuración con viaje en el tiempo y la posibilidad de construir nuevos modelos de lectura retroactivamente a partir de eventos existentes. Tu registro de eventos se convierte en la única fuente de verdad.

Lo que goes hace diferente

goes elimina la complejidad del Event Sourcing en Go. Sin boilerplate, sin DSL: solo interfaces de Go y generics. Comienzas con backends en memoria y cambias a MongoDB, PostgreSQL o NATS sin modificar una sola línea de código de dominio. El framework se encarga del enrutamiento de eventos, la hidratación de Aggregates, la gestión de snapshots y la programación de Projections. Tú te concentras en tu dominio.

Así funciona

La canalización de eventos

Cada cambio de estado fluye a través de una canalización claramente definida. Los Commands activan la lógica del Aggregate, que produce eventos. Los eventos se persisten y se proyectan en modelos de lectura.

1
Command

Una intención tipada se despacha y se valida mediante una cadena de middleware.

2
Aggregate

El Aggregate aplica invariantes y produce eventos a partir de Commands.

3
Evento

Un hecho inmutable que describe un cambio de estado. Fuente única de verdad.

4
Event Store

Los eventos se persisten de forma append-only y se distribuyen a los suscriptores.

5
Projection

Los modelos de lectura se construyen a partir del stream de eventos, en vivo o bajo demanda.

Arquitectura

Conceptos principales

Aggregates con Event Sourcing

Inserta el tipo base, registra controladores de eventos tipados. El framework se encarga del versionado, la persistencia y la reproducción. Los Aggregates son structs de Go normales con un aggregate.Base insertado. Los controladores de eventos se registran mediante funciones genéricas y se invocan automáticamente durante la hidratación. Los soft deletes, el versionado de Aggregates y el control de concurrencia optimista están disponibles desde el inicio.

Eventos distribuidos

Publica y suscríbete a eventos mediante NATS JetStream. MongoDB y PostgreSQL como Event Stores. Cambia de backend sin modificar el código. El Event Bus abstrae el transporte y la entrega. Tu código trabaja con eventos tipados, ya sea localmente, dentro del proceso o distribuidos en un clúster.

Commands con seguridad de tipos

Despacha y gestiona Commands con total seguridad de tipos genéricos. De forma síncrona o asíncrona, según el caso de uso. El Command Bus admite middleware, propagación de contexto y gestión de errores. Los Commands asíncronos se despachan a través del Event Bus; los síncronos, directamente en el proceso.

Kit de herramientas para Projections

Construye modelos de lectura con programaciones continuas o periódicas. Seguimiento automático del progreso, debouncing y recuperación al inicio. Las Projections pueden leer de cualquier Event Store y escribir en cualquier base de datos de lectura. El Scheduler se encarga de los reintentos en caso de error, el backoff y el procesamiento garantizado.

Codec Registry

Asigna nombres de eventos a tipos de Go para una serialización automática. JSON por defecto, MessagePack o Protobuf con un cambio de una línea. El Codec Registry es central para el manejo de eventos con seguridad de tipos. Garantiza que los eventos se serialicen, deserialicen y versionen correctamente.

Snapshots

Captura el estado de un Aggregate en un momento dado. Reproduce solo los eventos recientes en lugar de todo el historial. Los snapshots se crean automáticamente según intervalos configurables. Se admiten Stores de MongoDB, PostgreSQL y en memoria, con la misma arquitectura de backend conectable que el Event Store.

Diseñado para pruebas

Aserciones de prueba fluidas para Aggregates, backends en memoria para pruebas de integración y suites de conformidad para implementaciones personalizadas. El paquete de pruebas ofrece aserciones de estilo Expect: given Events, when Command, then Events. Las suites de conformidad garantizan que las implementaciones personalizadas de Event Store se comporten correctamente.

Diseño modular

Usa solo lo que necesitas —sistema de eventos, Commands, Projections— y añade más componentes cuando sea necesario. Cada paquete tiene interfaces claramente definidas y dependencias mínimas. Puedes integrar goes gradualmente en un proyecto existente sin tener que adoptar todo de una vez.

Backends

Backends listos para producción

goes sigue el principio de backends intercambiables: cada Event Store, Snapshot Store y Event Bus implementa una interfaz común. Desarrollas contra abstracciones, no contra implementaciones. Esto permite realizar pruebas locales con backends en memoria, usar MongoDB en staging y PostgreSQL con NATS en producción, sin modificar una sola línea de código de dominio.

MongoDB

Event Store basado en documentos con soporte nativo de Change Streams para suscripciones a eventos en tiempo real. Ideal para arquitecturas orientadas a eventos en las que las Projections deben reaccionar a nuevos eventos en tiempo real. También admite snapshots y concurrencia optimista mediante versionado de documentos.

PostgreSQL

Event Store relacional con transacciones ACID y control de concurrencia optimista. Perfecto para equipos que ya cuentan con una configuración de PostgreSQL y no desean introducir infraestructura adicional. El aislamiento serializable garantiza flujos de eventos coherentes.

NATS JetStream

Event Bus distribuido con entrega al menos una vez, grupos de consumidores y escalado horizontal. NATS es especialmente adecuado para arquitecturas de microservicios donde los eventos deben distribuirse entre servicios. Persistencia mediante JetStream, reproducción mediante offsets de consumidor.

En memoria

Backend sin configuración para prototipado y pruebas. La misma API que los backends de producción, para que las pruebas y los prototipos utilicen código idéntico al de producción. Sin configuración, sin dependencias, listo al instante.

3D interactivo

Arquitectura de microservicios

goes constituye la columna vertebral de los sistemas de microservicios orientados a eventos. Cada servicio se comunica a través del Event Bus central. Desplázate para explorar cada componente.

Aggregates1/8

Entidades de dominio que encapsulan la lógica de negocio y aplican invariantes. El Aggregate es el límite de consistencia para los eventos.

Tecnología

Stack tecnológico

Go NATS JetStream MongoDB PostgreSQL Protocol Buffers gRPC Docker
GitHub
158

GitHub Stars

Licencia

Apache-2.0

Idioma

Go

Forks

17

Contribuidores

5+

Ver en GitHub

FAQ

Preguntas frecuentes sobre goes

Sí. goes se utiliza en varios sistemas de producción y cuenta con mantenimiento activo. El framework tiene una API estable y modernice lo utiliza internamente para proyectos de clientes. Proyectos como Crovillas, DepositDirect y Prestige Cars funcionan con goes desde 2021.

goes admite MongoDB, PostgreSQL y NATS JetStream como backends de producción. Para pruebas y prototipado, existen implementaciones completas en memoria. Todos los backends implementan las mismas interfaces, lo que permite cambiarlos sin modificar el código.

Bastan conocimientos básicos de Go. La guía de inicio y el tutorial de 12 capítulos explican todos los conceptos paso a paso. goes está diseñado para que puedas aprender y aplicar patrones de Event Sourcing de forma incremental.

Sí. goes tiene una estructura modular. Puedes utilizar componentes individuales, como el sistema de eventos o los Commands, de forma independiente e integrar otros cuando los necesites. No existe una dependencia de todo o nada.

goes está diseñado para escenarios de alto rendimiento. Los snapshots reducen drásticamente el tiempo de reproducción, las Projections se ejecutan de forma asíncrona y paralela, y el Event Store admite procesamiento por lotes. En producción se procesan varios millones de eventos sin latencia perceptible.

EventStoreDB es una base de datos independiente, mientras que goes utiliza tu infraestructura existente (MongoDB, PostgreSQL, NATS). Axon está basado en Java y es considerablemente más opinionated. goes te proporciona los componentes y te permite decidir cómo combinarlos. Sin dependencias de runtime fuera del backend que elijas.

goes requiere Go 1.23 o posterior. El framework utiliza intensivamente Go Generics para garantizar la seguridad de tipos en Commands, eventos y Aggregates. Recomendamos utilizar siempre la versión estable más reciente de Go.

Las contribuciones son bienvenidas. El mejor punto de partida es el repositorio de GitHub. Los issues etiquetados como 'good first issue' son ideales para comenzar. Los PR se revisan y fusionan con rapidez. Para cambios mayores, recomendamos crear primero un issue para acordar el enfoque.

Ponte en contacto con nosotros

¿Usas goes o estás valorando si event sourcing encaja en tu proyecto? Contáctanos, nos gusta hablar de arquitectura y de experiencia en producción.