Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions lib/maestro/aggregate/root.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ defmodule Maestro.Aggregate.Root do

def replay(agg_id, seq), do: call(agg_id, {:replay, seq})

def evaluate(%Maestro.Types.Command{} = command) do
call(command.aggregate_id, {:eval_command, command})
def evaluate(command, opts \\ [])

def evaluate(%Maestro.Types.Command{} = command, opts) do
call(command.aggregate_id, {:eval_command, command, opts})
end

def evaluate(_), do: raise(ArgumentError, "invalid command")
def evaluate(_, _), do: raise(ArgumentError, "invalid command")

def snapshot(agg_id) do
with {:ok, snap} <- call(agg_id, :get_snapshot) do
Expand Down Expand Up @@ -166,8 +168,17 @@ defmodule Maestro.Aggregate.Root do
err -> {:reply, {:error, err, __STACKTRACE__}, agg}
end

def handle_call({:eval_command, command}, _from, agg) do
{:reply, :ok, Root.eval_command(agg, command)}
def handle_call({:eval_command, command, opts}, _from, agg) do
{:ok, agg, events} = Root.eval_command(agg, command)

result =
case opts[:return] do
:state -> {:ok, agg.state}
:events -> {:ok, events}
_ -> :ok
end

{:reply, result, agg}
rescue
err -> {:reply, {:error, err, __STACKTRACE__}, agg}
end
Expand Down Expand Up @@ -234,10 +245,23 @@ defmodule Maestro.Aggregate.Root do
"""
@callback replay(id(), sequence()) :: {:ok, any()} | {:error, any(), stack()}

@type evaluate_opt :: {:return, :events | :state}
@type evaluate_opts :: [evaluate_opt()]

@doc """
Evaluate the command within the aggregate's context.
Evaluate the command within the aggregate's context. With the option `:return` return either the events or the state.
"""
@callback evaluate(command()) :: :ok | {:error, any(), stack()}
@callback evaluate(command()) ::
:ok
| {:ok, [Maestro.Types.Event.t()]}
| {:ok, state :: any()}
| {:error, any(), stack()}

@callback evaluate(command(), evaluate_opts()) ::
:ok
| {:ok, [Maestro.Types.Event.t()]}
| {:ok, state :: any()}
| {:error, any(), stack()}

@doc """
Using the aggregate root's `prepare_snapshot` function, generate and store a
Expand Down Expand Up @@ -345,8 +369,9 @@ defmodule Maestro.Aggregate.Root do
with agg <- update_aggregate(agg),
com_module <- lookup_module(agg.command_prefix, command.type),
events <- com_module.eval(agg, command),
events <- prepare_events(agg, events) do
persist_events(agg, command, events)
events <- prepare_events(agg, events),
agg <- persist_events(agg, command, events) do
{:ok, agg, events}
end
end

Expand All @@ -371,9 +396,12 @@ defmodule Maestro.Aggregate.Root do
apply_events(agg, events)

{:error, :retry_command} ->
{:ok, agg, _events} =
agg
|> update_aggregate()
|> eval_command(command)

agg
|> update_aggregate()
|> eval_command(command)
end
end

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Maestro.Mixfile do
use Mix.Project

@version "0.4.0"
@version "0.5.0"
@source_url "https://github.com/elixir-toniq/maestro"

def project do
Expand Down
31 changes: 31 additions & 0 deletions test/maestro/aggregate_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,37 @@ defmodule Maestro.AggregateTest do
assert value == 3
end

test "return options" do
{:ok, agg_id} = SampleAggregate.new()

{:ok, %{"value" => value}} = SampleAggregate.get(agg_id)
assert value == 0

{:ok, events} =
SampleAggregate.evaluate(
%Command{
type: "increment_counter",
aggregate_id: agg_id,
data: %{}
},
return: :events
)

assert [%{type: "counter_incremented"}] = events

{:ok, state} =
SampleAggregate.evaluate(
%Command{
type: "increment_counter",
aggregate_id: agg_id,
data: %{}
},
return: :state
)

assert %{"value" => 2} = state
end

test "recover an intermediate state" do
{:ok, agg_id} = SampleAggregate.new()

Expand Down