Maestro v0.1.0 Maestro.Aggregate.Root behaviour View Source
Core behaviour and functionality provided by Maestro for processing commands and managing aggregate state.
Traditional domain entities are referred to as aggregates in the literature. At the outermost edge of a bounded context, you find an aggregate root. The goal of this library is to greatly simplify the process of implementing an event sourced application by owning the flow of non-domain data (i.e. commands, events, and snapshots) to allow you to focus on the business logic of evaluating your commands and applying the subsequent events to your domain objects.
The most crucial piece to this is the aggregate root.
Maestro.Aggregate.CommandHandler
defines a behaviour
with the goal of
isolating a single command handler’s eval
. Similarly, there is the
Maestro.Aggregate.EventHandler
behaviour which defines how to apply
that
event to the aggregate. With these key components modeled explicitly, the
Maestro.Aggregate.Root
focuses on the dataflow and ensuring that queries to
aggregate state flow properly.
The aggregate root dispatches to the particular command handlers and event
handlers by means of an opinionated dynamic dispatch. To ensure that these
things are handled in a consistent manner, the aggregate root is modeled as a
GenServer
and provides the requisite lifecycle hooks.
use Maestro.Aggregate.Root
takes the following options:
:command_prefix
- module prefix for finding commands:event_prefix
- module prefix for finding events
Link to this section Summary
Functions
struct to event type of the form “The.ModuleName -> the.module_name” dropping the provided prefix for conciseness
Callbacks
If you extend the aggregate to provide other functionality, call
is
available to assist in pushing that functionality into the aggregate’s
context
Evaluate the command within the aggregate’s context
Forces the aggregate to retrieve any events. Since Maestro operates in a node-local manner, it’s entirely possible some other node has processed commands/events
A (potentially) stale read of the aggregate’s state. If you want to ensure the
state is as up-to-date as possible, see fetch/1
When an aggregate root is created, this callback is invoked to generate the state
Create a new aggregate along with the provided initial_state
function. This
function should only fail if there was a problem generating an HLC timestamp
Snapshots are stored in a single-row-per-aggregate manner and are used to make it easier/faster to hydrate the aggregate root. This function should return the map which will be JSON encoded when moving to a durable store
Recover a past version of the aggregate’s state by specifying a maximum sequence number. The aggregate’s snapshot and any/all events will be used to get the state back to that point
Using the aggregate root’s prepare_snapshot
function, generate and store a
snapshot. Useful if there are a lot of events, big events, or just a healthy
amount of aggregate state to compose
Moving from the snapshotted representation to the aggregate root’s structure can be a complicated process that requires custom hooks. Otherwise, a default implementation is provided that simply lifts the map out of the snapshot and uses it as the state of the aggregate
Link to this section Types
Link to this section Functions
struct to event type of the form “The.ModuleName -> the.module_name” dropping the provided prefix for conciseness
Link to this section Callbacks
If you extend the aggregate to provide other functionality, call
is
available to assist in pushing that functionality into the aggregate’s
context.
Evaluate the command within the aggregate’s context.
Forces the aggregate to retrieve any events. Since Maestro operates in a node-local manner, it’s entirely possible some other node has processed commands/events.
A (potentially) stale read of the aggregate’s state. If you want to ensure the
state is as up-to-date as possible, see fetch/1
.
When an aggregate root is created, this callback is invoked to generate the state
Create a new aggregate along with the provided initial_state
function. This
function should only fail if there was a problem generating an HLC timestamp.
Snapshots are stored in a single-row-per-aggregate manner and are used to make it easier/faster to hydrate the aggregate root. This function should return the map which will be JSON encoded when moving to a durable store.
Recover a past version of the aggregate’s state by specifying a maximum sequence number. The aggregate’s snapshot and any/all events will be used to get the state back to that point.
Using the aggregate root’s prepare_snapshot
function, generate and store a
snapshot. Useful if there are a lot of events, big events, or just a healthy
amount of aggregate state to compose.
use_snapshot(root :: t(), snapshot :: Maestro.Types.Snapshot.t()) :: any()
Moving from the snapshotted representation to the aggregate root’s structure can be a complicated process that requires custom hooks. Otherwise, a default implementation is provided that simply lifts the map out of the snapshot and uses it as the state of the aggregate.