Skip to content

v0.1.0

Latest

Choose a tag to compare

@alexeyzimarev alexeyzimarev released this 20 Mar 16:52
· 14 commits to main since this release
b042d15

Eventuous for Go — v0.1.0

First release of the Go port of Eventuous, a production-grade Event Sourcing library.

What's included

Core module (github.com/eventuous/eventuous-go/core)

  • Domain: Aggregate[S] with fold pattern, Apply, guards (EnsureNew/EnsureExists)
  • Persistence: EventReader/EventWriter/EventStore interfaces, LoadState, LoadAggregate, StoreAggregate
  • Serialization: TypeMap (bidirectional type registry), Codec interface, JSON implementation
  • Command services: Functional Service[S] (primary) and AggregateService[S] (optional DDD pattern)
  • Subscriptions: EventHandler with middleware chain (WithConcurrency, WithPartitioning, WithLogging), CheckpointCommitter with gap detection
  • Test infrastructure: In-memory store, store conformance test suite, subscription conformance test suite, shared Booking test domain

KurrentDB module (github.com/eventuous/eventuous-go/kurrentdb)

  • Full EventStore implementation (append, read forward/backward, delete, truncate)
  • Catch-up subscriptions (stream + $all) with checkpoint support and auto-reconnect
  • Persistent subscriptions (stream + $all) with ack/nack
  • Integration tests via testcontainers

OpenTelemetry module (github.com/eventuous/eventuous-go/otel)

  • TracedCommandHandler decorator (tracing spans + duration histogram + error counter)
  • TracingMiddleware for subscriptions

Installation

go get github.com/eventuous/eventuous-go/core@v0.1.0
go get github.com/eventuous/eventuous-go/kurrentdb@v0.1.0
go get github.com/eventuous/eventuous-go/otel@v0.1.0

Quick example

// Define state + fold
type BookingState struct { ID, RoomID string; Active bool }

func bookingFold(state BookingState, event any) BookingState {
    switch e := event.(type) {
    case RoomBooked:
        return BookingState{ID: e.BookingID, RoomID: e.RoomID, Active: true}
    default:
        return state
    }
}

// Create command service
svc := command.New[BookingState](store, store, bookingFold, BookingState{})

command.On(svc, command.Handler[BookRoom, BookingState]{
    Expected: eventuous.IsNew,
    Stream:   func(cmd BookRoom) eventuous.StreamName { return eventuous.NewStreamName("Booking", cmd.BookingID) },
    Act:      func(ctx context.Context, state BookingState, cmd BookRoom) ([]any, error) {
        return []any{RoomBooked{BookingID: cmd.BookingID, RoomID: cmd.RoomID}}, nil
    },
})

result, err := svc.Handle(ctx, BookRoom{BookingID: "123", RoomID: "room-42"})

Design principles

  • Functional-first — pure functions over OOP, type switch fold over handler registration
  • Idiomatic Go — composition over inheritance, middleware chains, context.Context + errors
  • Multi-module — import only what you need, no transitive dependency bloat