Packages
commanded
0.16.0-rc.0
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.0
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.1
1.0.0-rc.0
0.19.1
0.19.0
0.18.1
0.18.0
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.16.0-rc.1
0.16.0-rc.0
0.15.1
0.15.0
0.14.0
0.14.0-rc.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.5
0.8.4
0.8.3
0.8.1
0.8.0
0.7.1
0.6.2
0.6.1
0.6.0
0.4.0
0.3.1
0.3.0
0.2.1
0.2.0
0.1.0
Use Commanded to build your own Elixir applications following the CQRS/ES pattern.
Current section
Files
Jump to
Current section
Files
test/aggregates/aggregate_subscription_test.exs
defmodule Commanded.Aggregates.AggregateSubscriptionTest do
use Commanded.StorageCase
alias Commanded.Aggregates.{Aggregate, ExecutionContext}
alias Commanded.Aggregates.Supervisor, as: AggregateSupervisor
alias Commanded.{EventStore, Registration}
alias Commanded.ExampleDomain.{BankAccount, OpenAccountHandler}
alias Commanded.ExampleDomain.BankAccount.Commands.OpenAccount
alias Commanded.ExampleDomain.BankAccount.Events.MoneyDeposited
describe "append event directly to aggregate stream" do
setup [
:open_account,
:append_event_to_stream
]
test "should notify aggregate and mutate its state", context do
%{account_number: account_number} = context
assert Aggregate.aggregate_version(BankAccount, account_number) == 2
assert Aggregate.aggregate_state(BankAccount, account_number) == %BankAccount{
account_number: account_number,
balance: 1_500,
state: :active
}
end
test "should ignore already seen events", context do
%{account_number: account_number} = context
pid = Registration.whereis_name({BankAccount, account_number})
events = account_number |> EventStore.stream_forward() |> Enum.to_list()
# send already seen events multiple times, they should be ignored
send(pid, {:events, events})
send(pid, {:events, events})
send(pid, {:events, events})
send(pid, {:events, events})
assert Aggregate.aggregate_version(BankAccount, account_number) == 2
assert Aggregate.aggregate_state(BankAccount, account_number) == %BankAccount{
account_number: account_number,
balance: 1_500,
state: :active
}
end
test "should stop aggregate process when unexpected event received", context do
%{account_number: account_number} = context
pid = Registration.whereis_name({BankAccount, account_number})
ref = Process.monitor(pid)
events =
account_number
|> EventStore.stream_forward()
|> Enum.to_list()
|> Enum.map(fn recorded_event ->
# specify invalid stream version
%EventStore.RecordedEvent{
recorded_event
| stream_version: 999
}
end)
# send invalid events, should stop the aggregate process
send(pid, {:events, events})
assert_receive {:DOWN, ^ref, :process, _, :unexpected_event_received}
end
defp open_account(_context) do
account_number = UUID.uuid4()
{:ok, ^account_number} = AggregateSupervisor.open_aggregate(BankAccount, account_number)
context = %ExecutionContext{
command: %OpenAccount{account_number: account_number, initial_balance: 1_000},
handler: OpenAccountHandler,
function: :handle,
retry_attempts: 1
}
{:ok, 1, _events} = Aggregate.execute(BankAccount, account_number, context)
[
account_number: account_number
]
end
# Write an event to the aggregate's stream, bypassing the aggregate process
defp append_event_to_stream(%{account_number: account_number}) do
event = %Commanded.EventStore.EventData{
event_type: "Elixir.Commanded.ExampleDomain.BankAccount.Events.MoneyDeposited",
data: %MoneyDeposited{
account_number: account_number,
transfer_uuid: UUID.uuid4(),
amount: 500,
balance: 1_500
}
}
{:ok, _} = EventStore.append_to_stream(account_number, 1, [event])
:ok
end
end
end