esrc

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2022 License: MIT Imports: 7 Imported by: 1

README

esrc

An event sourcing library in Go

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAggregateNotFound                       = errors.New("aggregate not found")
	ErrAggregateAlreadyExists                  = errors.New("aggregate already exists")
	ErrAggregateRequiresEvents                 = errors.New("an aggregate requires events")
	ErrOptimisticConcurrency                   = errors.New("optimistic concurrency error")
	ErrSnapshotWithGreaterVersionThanAggregate = errors.New("snapshot version is greater than that of the aggregate")
)

Functions

This section is empty.

Types

type Aggregate

type Aggregate interface {
	ID() ID
	InitialVersion() int
	Changes() []Event
	Snapshot() ([]byte, error)
}

type AggregateFactory

type AggregateFactory[T Aggregate] interface {
	NewAggregateFromSnapshotAndEvents(RawSnapshot, []Event) (T, error)
	NewAggregateFromEvents([]Event) (T, error)
}

type AggregateType

type AggregateType string

AggregateType is stored as part of the event stream, needed when IDs are only unique within the same AggregateType

type Event

type Event interface {
	EventName() string
}

Event must be implemented by domain events

type EventFactory

type EventFactory interface {
	CreateEmptyEvent(name string) (Event, error)
}

EventFactory is the abstraction needed to create the Event associated to an EventName

type EventMarshaler

type EventMarshaler interface {
	MarshalEvent(Event) ([]byte, error)
	UnmarshalEvent([]byte, Event) error
}

EventMarshaler marshals and unmarshals an Event's data/body

type EventRaiserAggregate

type EventRaiserAggregate struct {
	// contains filtered or unexported fields
}

EventRaiserAggregate is a helper struct that can be embbeded in real aggregates, handles the execution of raised events and keeps track of versioning

func NewEventRaiserAggregate

func NewEventRaiserAggregate(onEvent func(Event)) EventRaiserAggregate

func NewEventRaiserAggregateFromEvents

func NewEventRaiserAggregateFromEvents(initialVersion int, events []Event, onEvent func(Event)) EventRaiserAggregate

func (EventRaiserAggregate) Changes

func (a EventRaiserAggregate) Changes() []Event

func (EventRaiserAggregate) InitialVersion

func (a EventRaiserAggregate) InitialVersion() int

func (*EventRaiserAggregate) Raise

func (a *EventRaiserAggregate) Raise(e Event)

type EventStore

type EventStore interface {
	// AddAggregate adds a new aggregate to the event store.
	// errs:
	// 		ErrAggregateAlreadyExists
	//		ErrAggregateRequiresEvents
	AddAggregate(context.Context, AggregateType, ID, []RawEvent) error
	// AppendEvents adds events to an existing aggregate.
	// errs:
	//		ErrAggregateNotFound
	//		ErrOptimisticConcurrency
	AppendEvents(ctx context.Context, t AggregateType, id ID, fromVersion int, events []RawEvent) error
	// AddSnapshot stores a snapshot of an aggregate.
	// errs:
	//		ErrAggregateNotFound
	//		ErrSnapshotWithGreaterVersionThanAggregate
	AddSnapshot(context.Context, AggregateType, ID, RawSnapshot) error
	// LatestSnapshot retrieves the snapshot with higher version of an aggregate. Returns a nil snapshot if there isn't any.
	LatestSnapshot(context.Context, AggregateType, ID) (*RawSnapshot, error)
	// Events retrieves all events of an aggregate from a given event number. If requested from event 0 all events
	// are obtained.
	Events(ctx context.Context, t AggregateType, id ID, fromEventNumber int) ([]RawEvent, error)
	// Contains looks if there is an event stream for an aggregate ID without loading its events,
	// returns true if the aggregate exists.
	ContainsAggregate(context.Context, AggregateType, ID) (bool, error)
}

EventStore persists and loads aggregates as a sequence of events. Implementations must ensure optimistic concurrency.

type ID

type ID any

ID is the aggregate id, modeled as empty interface since it's a specific domain concern. Ideally, the EventStore's implementation should be able to handle different id types by configuration.

type JSONEventMarshaler

type JSONEventMarshaler struct{}

func (JSONEventMarshaler) MarshalEvent

func (JSONEventMarshaler) MarshalEvent(e Event) ([]byte, error)

func (JSONEventMarshaler) UnmarshalEvent

func (JSONEventMarshaler) UnmarshalEvent(b []byte, e Event) error

type MockAggregate

type MockAggregate struct {
	IDFn             func() ID
	InitialVersionFn func() int
	ChangesFn        func() []Event
	SnapshotFn       func() ([]byte, error)
}

func (*MockAggregate) Changes

func (m *MockAggregate) Changes() []Event

func (*MockAggregate) ID

func (m *MockAggregate) ID() ID

func (*MockAggregate) InitialVersion

func (m *MockAggregate) InitialVersion() int

func (*MockAggregate) Snapshot

func (m *MockAggregate) Snapshot() ([]byte, error)

type MockAggregateFactory

type MockAggregateFactory[T Aggregate] struct {
	NewAggregateFromSnapshotAndEventsFn func(RawSnapshot, []Event) (T, error)
	NewAggregateFromEventsFn            func([]Event) (T, error)
}

func (*MockAggregateFactory[T]) NewAggregateFromEvents

func (m *MockAggregateFactory[T]) NewAggregateFromEvents(events []Event) (T, error)

func (*MockAggregateFactory[T]) NewAggregateFromSnapshotAndEvents

func (m *MockAggregateFactory[T]) NewAggregateFromSnapshotAndEvents(snapshot RawSnapshot, events []Event) (T, error)

type MockEvent

type MockEvent struct {
	EventNameFn func() string
}

func (*MockEvent) EventName

func (m *MockEvent) EventName() string

type MockEventFactory

type MockEventFactory struct {
	CreateEmptyEventFn func(name string) (Event, error)
}

func (*MockEventFactory) CreateEmptyEvent

func (m *MockEventFactory) CreateEmptyEvent(name string) (Event, error)

type MockEventMarshaler

type MockEventMarshaler struct {
	MarshalEventFn   func(Event) ([]byte, error)
	UnmarshalEventFn func([]byte, Event) error
}

func (*MockEventMarshaler) MarshalEvent

func (m *MockEventMarshaler) MarshalEvent(e Event) ([]byte, error)

func (*MockEventMarshaler) UnmarshalEvent

func (m *MockEventMarshaler) UnmarshalEvent(b []byte, e Event) error

type MockEventStore

type MockEventStore struct {
	AddAggregateFn      func(context.Context, AggregateType, ID, []RawEvent) error
	AppendEventsFn      func(ctx context.Context, t AggregateType, id ID, fromVersion int, events []RawEvent) error
	AddSnapshotFn       func(context.Context, AggregateType, ID, RawSnapshot) error
	LatestSnapshotFn    func(context.Context, AggregateType, ID) (*RawSnapshot, error)
	EventsFn            func(context.Context, AggregateType, ID, int) ([]RawEvent, error)
	ContainsAggregateFn func(context.Context, AggregateType, ID) (bool, error)
}

func (*MockEventStore) AddAggregate

func (m *MockEventStore) AddAggregate(ctx context.Context, t AggregateType, id ID, re []RawEvent) error

func (*MockEventStore) AddSnapshot

func (m *MockEventStore) AddSnapshot(ctx context.Context, t AggregateType, id ID, snapshot RawSnapshot) error

func (*MockEventStore) AppendEvents

func (m *MockEventStore) AppendEvents(ctx context.Context, t AggregateType, id ID, fromVersion int, events []RawEvent) error

func (*MockEventStore) ContainsAggregate

func (m *MockEventStore) ContainsAggregate(ctx context.Context, t AggregateType, id ID) (bool, error)

func (*MockEventStore) Events

func (m *MockEventStore) Events(ctx context.Context, t AggregateType, id ID, fromEventNumber int) ([]RawEvent, error)

func (*MockEventStore) LatestSnapshot

func (m *MockEventStore) LatestSnapshot(ctx context.Context, t AggregateType, id ID) (*RawSnapshot, error)

type RawEvent

type RawEvent struct {
	Name string
	Data []byte
}

RawEvent is the marshaled version of an Event

func MarshalEvents

func MarshalEvents(events []Event, marshaler EventMarshaler) ([]RawEvent, error)

MarshalEvents marshals Events to RawEvents (in the same order) given an EventMarshaler, if an error happens marshalling an Event, the events marshalled succesfully before that event are returned along with the error.

type RawSnapshot

type RawSnapshot struct {
	Version int
	Data    []byte
}

type Repository

type Repository[T Aggregate] struct {
	// contains filtered or unexported fields
}

Repository is a layer on top of an EventStore that reduces the boilerplate needed to build an event sourced aggregate repository

func NewRepository

func NewRepository[T Aggregate](es EventStore, af AggregateFactory[T], ef EventFactory, opts ...RepositoryOption[T]) *Repository[T]

func (*Repository[T]) Add

func (r *Repository[T]) Add(ctx context.Context, aggregate T) error

func (*Repository[T]) Contains

func (r *Repository[T]) Contains(ctx context.Context, id ID) (bool, error)

func (*Repository[T]) FindByID

func (r *Repository[T]) FindByID(ctx context.Context, id ID) (T, error)

func (*Repository[T]) Update

func (r *Repository[T]) Update(ctx context.Context, aggregate T) error

func (*Repository[T]) UpdateByID

func (r *Repository[T]) UpdateByID(ctx context.Context, id ID, update func(aggregate T) error) error

type RepositoryOption

type RepositoryOption[T Aggregate] func(*Repository[T])

func RepositoryWithEventsMarshaler

func RepositoryWithEventsMarshaler[T Aggregate](eventMarshaler EventMarshaler) RepositoryOption[T]

func RepositoryWithEventsPerSnapshot

func RepositoryWithEventsPerSnapshot[T Aggregate](eventsPerSnapshot int) RepositoryOption[T]

func RepositoryWithLogger

func RepositoryWithLogger[T Aggregate](log log.Logger) RepositoryOption[T]

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL