Disco v0.1.3 Disco.Aggregate behaviour View Source

The aggregate specification.

An aggregate in Disco is a struct which has the fields representing the state of itself.

This module defines a behaviour with a set of default callback implementations to execute a command or a query on the aggregate.

Define an aggregate

Here’s how to implement a simple aggregate:

defmodule MyApp.Aggregate do
  defstruct id: nil, foo: nil

  use Disco.Aggregate,
    routes: %{
      commands: %{
        do_something: MyApp.Commands.DoSomething
      },
      queries: %{
        find_something: MyApp.Commands.FindSomething
      }
    },
    event_store_client: MyApp.EventStoreClient

  def apply_event(%{type: "SomethingDone"} = event, state) do
    %{state | foo: event.foo, id: event.aggregate_id}
  end
end

NOTE

It is very important to always specify an id field in the aggregate struct. Every aggregate needs it to be uniquely identified.

Overriding default functions

The simplest implementation only requires to implement apply_event/2 callback, while the others are already implemented by default. Sometimes you might need a custom implementation of the callbacks, that’s why it’s possible to easily override them.

Usage example

NOTE: Disco.Factories.ExampleAggregate has been defined in test/support/examples/example_aggregate.ex.

iex> alias Disco.Factories.ExampleAggregate, as: Aggregate
iex> Aggregate.commands()
[:do_something]
iex> Aggregate.routes()
[:find_something]
iex> Aggregate.dispatch(:do_something, %{foo: "bar"})
{:ok, %Disco.Factories.ExampleAggregate{
  foo: "bar",
  id: "4fd98a9e-8d6f-4e35-a8fc-aca5544596cb"
}}
iex> Aggregate.query(:find_something, %{foo: "bar"})
%{foo: "bar"}

Umbrella apps

Check Disco.Orchestrator.

Link to this section Summary

Types

Represents the state of an aggregate

Functions

Defines the default callbacks to implement the behaviour, the routes to commands and queries, sets the client to communicate with the Disco.EventStore

Callbacks

Called to apply an event to update the state

Called to send emitted events to Disco.EventStore

Called to get the current aggregate state

Called to run a given command and to emit the event(s). Returns updated state

Called to process a list events to update the state

Link to this section Types

Represents the state of an aggregate.

Link to this section Functions

Link to this macro __using__(opts \\ []) View Source (macro)

Defines the default callbacks to implement the behaviour, the routes to commands and queries, sets the client to communicate with the Disco.EventStore.

Options

  • :routes - a map with :commands and :queries as keys, and a map with query_name: query_module pairs, as value.
  • :event_store_client - a module that implements Disco.EventStore.Client behaviour.

Link to this section Callbacks

Link to this callback apply_event(event, state) View Source
apply_event(event :: map(), state()) :: state()

Called to apply an event to update the state.

Link to this callback commit(events) View Source
commit(events :: list()) :: :ok

Called to send emitted events to Disco.EventStore.

Link to this callback current_state(id) View Source
current_state(id :: any()) :: state()

Called to get the current aggregate state.

Link to this callback handle(command, aggregate_id) View Source
handle(command :: map(), aggregate_id :: binary() | nil) :: {:ok, state()}

Called to run a given command and to emit the event(s). Returns updated state.

Link to this callback process(events, state) View Source
process(events :: list(), state()) :: {:ok, state()}

Called to process a list events to update the state.