Documentation ¶
Overview ¶
Package aggregate defines interfaces and types necessary to allow users to define their own Aggregate types.
Index ¶
- Variables
- func RecordThat[I ID](root Root[I], events ...event.Envelope) error
- func RehydrateFromEvents[I ID](root Root[I], eventStream event.StreamRead) error
- func RehydrateFromState[I ID, Src Root[I], Dst any](v version.Version, dst Dst, deserializer serde.Deserializer[Src, Dst]) (Src, error)
- type Aggregate
- type BaseRoot
- type EventSourcedRepository
- type Factory
- type FusedRepository
- type Getter
- type ID
- type Internal
- type Repository
- type Root
- type Saver
- type ScenarioGiven
- type ScenarioInit
- type ScenarioThen
- type ScenarioWhen
- func (sc ScenarioWhen[I, T]) Then(v version.Version, events ...event.Envelope) ScenarioThen[I, T]
- func (sc ScenarioWhen[I, T]) ThenError(err error) ScenarioThen[I, T]
- func (sc ScenarioWhen[I, T]) ThenErrors(errs ...error) ScenarioThen[I, T]
- func (sc ScenarioWhen[I, T]) ThenFails() ScenarioThen[I, T]
- type Type
Constants ¶
This section is empty.
Variables ¶
var ErrRootNotFound = fmt.Errorf("aggregate: root not found")
ErrRootNotFound is returned when the Aggregate Root requested through a Repository was not found.
Functions ¶
func RecordThat ¶
RecordThat records the Domain Event for the specified Aggregate Root.
An error is typically returned if applying the Domain Event on the Aggregate Root instance fails with an error.
func RehydrateFromEvents ¶
func RehydrateFromEvents[I ID](root Root[I], eventStream event.StreamRead) error
RehydrateFromEvents rehydrates an Aggregate Root from a read-only Event Stream.
func RehydrateFromState ¶
func RehydrateFromState[I ID, Src Root[I], Dst any]( v version.Version, dst Dst, deserializer serde.Deserializer[Src, Dst], ) (Src, error)
RehydrateFromState rehydrates an aggregate.Root instance using a state type, typically coming from an external state type (e.g. Protobuf type) and aggregate.Repository implementation (e.g. postgres.AggregateRepository).
Types ¶
type Aggregate ¶
type Aggregate interface { // Apply applies the specified Event to the Aggregate Root, // by causing a state change in the Aggregate Root instance. // // Since this method cause a state change, implementors should make sure // to use pointer semantics on their Aggregate Root method receivers. // // Please note, this method should not perform any kind of external request // and should be, save for the Aggregate Root state mutation, free of side effects. // For this reason, this method does not include a context.Context instance // in the input parameters. Apply(event.Event) error }
Aggregate is the segregated interface, part of the Aggregate Root interface, that describes the left-folding behavior of Domain Events to update the Aggregate Root state.
type BaseRoot ¶
type BaseRoot struct {
// contains filtered or unexported fields
}
BaseRoot segregates and completes the aggregate.Root interface implementation when embedded to a user-defined Aggregate Root type.
BaseRoot provides some common traits, such as tracking the current Aggregate Root version, and the recorded-but-uncommitted Domain Events, through the aggregate.RecordThat function.
func (*BaseRoot) FlushRecordedEvents ¶
FlushRecordedEvents returns the list of uncommitted, recorded Domain Events through the Aggregate Root.
The internal list kept by aggregate.BaseRoot is reset.
type EventSourcedRepository ¶
EventSourcedRepository provides an aggregate.Repository interface implementation that uses an event.Store to store and load the state of the Aggregate Root.
func NewEventSourcedRepository ¶
func NewEventSourcedRepository[I ID, T Root[I]](eventStore event.Store, typ Type[I, T]) EventSourcedRepository[I, T]
NewEventSourcedRepository returns a new EventSourcedRepository implementation to store and load Aggregate Roots, specified by the aggregate.Type, using the provided event.Store implementation.
func (EventSourcedRepository[I, T]) Get ¶
func (repo EventSourcedRepository[I, T]) Get(ctx context.Context, id I) (T, error)
Get returns the Aggregate Root with the specified id.
aggregate.ErrRootNotFound is returned if no Aggregate Root was found with that id.
An error is returned if the underlying Event Store fails, or if an error occurs while trying to rehydrate the Aggregate Root state from its Event Stream.
func (EventSourcedRepository[I, T]) Save ¶
func (repo EventSourcedRepository[I, T]) Save(ctx context.Context, root T) error
Save stores the Aggregate Root to the Event Store, by adding the new, uncommitted Domain Events recorded through the Root, if any.
An error is returned if the underlying Event Store fails.
type Factory ¶
Factory is a function that creates new zero-valued instances of an aggregate.Root implementation.
type FusedRepository ¶
FusedRepository is a convenience type that can be used to fuse together different implementations for the Getter and Saver Repository interface components.
type Getter ¶
Getter is an Aggregate Repository interface component, that can be used for retrieving Aggregate Roots from some storage.
type ID ¶
ID represents an Aggregate ID type.
Aggregate IDs should be able to be marshaled into a string format, in order to be saved onto a named Event Stream.
type Internal ¶
Internal contains some Aggregate Root methods that are used by internal packages and modules for this library.
Direct usage of these methods are discouraged.
type Repository ¶
Repository is an interface used to get Aggregate Roots from and save them to some kind of storage, depending on the implementation.
type Root ¶
type Root[I ID] interface { Aggregate Internal // AggregateID returns the Aggregate Root identifier. AggregateID() I // Version returns the current Aggregate Root version. // The version gets updated each time a new event is recorded // through the aggregate.RecordThat function. Version() version.Version // contains filtered or unexported methods }
Root is the interface describing an Aggregate Root instance.
This interface should be implemented by your Aggregate Root types. Make sure your Aggregate Root types embed the aggregate.BaseRoot type to complete the implementation of this interface.
type Saver ¶
Saver is an Aggregate Repository interface component, that can be used for storing Aggregate Roots in some storage.
type ScenarioGiven ¶
ScenarioGiven is the state of the scenario once the Aggregate Root preconditions have been set through the Scenario().Given() method.
This state gives access to the When() method to specify the aggregate method to test using the desired Aggregate Root.
func (ScenarioGiven[I, T]) When ¶
func (sc ScenarioGiven[I, T]) When(fn func(T) error) ScenarioWhen[I, T]
When allows to call the aggregate method method on the Aggregate Root instance provided by the previous Scenario().Given() call.
The aggregate method must be called inside the required closure parameter.
type ScenarioInit ¶
ScenarioInit is the entrypoint of the Aggregate Root scenario API.
An Aggregate Root scenario can either set the current evaluation context by using Given(), or test a "clean-slate" scenario by using When() directly.
func Scenario ¶
func Scenario[I ID, T Root[I]](typ Type[I, T]) ScenarioInit[I, T]
Scenario is a scenario type to test the result of methods called on an Aggregate Root and their effects.
These methods are meant to produce side-effects in the Aggregate Root state, and thus in the overall system, enforcing the aggregate invariants represented by the Aggregate Root itself.
func (ScenarioInit[I, T]) Given ¶
func (sc ScenarioInit[I, T]) Given(events ...event.Persisted) ScenarioGiven[I, T]
Given allows to set an Aggregate Root state as precondition to the scenario test, by specifying ordered Domain Events.
func (ScenarioInit[I, T]) When ¶
func (sc ScenarioInit[I, T]) When(fn func() (T, error)) ScenarioWhen[I, T]
When allows to call for a aggregate method/function that creates a new Aggregate Root instance.
This method requires a closure that return said new Aggregate Root instance (hence why no input parameter) or an error.
type ScenarioThen ¶
ScenarioThen is the state of the scenario where all parameters have been set and it's ready to be executed using a testing.T instance.
Use the AssertOn method to run the test scenario.
func (ScenarioThen[I, T]) AssertOn ¶
func (sc ScenarioThen[I, T]) AssertOn(t *testing.T)
AssertOn runs the test scenario using the specified testing.T instance.
type ScenarioWhen ¶
ScenarioWhen is the state of the scenario once the aggregate method to test has been provided through either Scenario().When() or Scenario().Given().When() paths.
This state allows to specify the expected outcome on the scenario using either Then(), ThenFails(), ThenError() or ThenErrors() methods.
func (ScenarioWhen[I, T]) Then ¶
func (sc ScenarioWhen[I, T]) Then(v version.Version, events ...event.Envelope) ScenarioThen[I, T]
Then specifies a successful outcome of the scenario, allowing to assert the expected new Aggregate Root version and Domain Events recorded during the aggregate method execution.
func (ScenarioWhen[I, T]) ThenError ¶
func (sc ScenarioWhen[I, T]) ThenError(err error) ScenarioThen[I, T]
ThenError specifies an unsuccessful outcome of the scenario, where the aggregate method execution fails with an error.
Use this method when you want to assert that the error retured by the aggregate method execution is of a specific type or value.
func (ScenarioWhen[I, T]) ThenErrors ¶
func (sc ScenarioWhen[I, T]) ThenErrors(errs ...error) ScenarioThen[I, T]
ThenErrors specifies an unsuccessful outcome of the scenario, where the aggregate method execution fails with a specific error that wraps multiple error types (e.g. through `errors.Join`).
Use this method when you want to assert that the error returned by the aggregate method matches ALL of the errors specified.
func (ScenarioWhen[I, T]) ThenFails ¶
func (sc ScenarioWhen[I, T]) ThenFails() ScenarioThen[I, T]
ThenFails specifies an unsuccessful outcome of the scenario, where the aggregate method execution fails with an error.
Use this method when there is no need to assert the error returned by the aggregate method is of a specific type or value.