Skip to content

Instantly share code, notes, and snippets.

@slashdotdash
Last active September 14, 2017 10:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slashdotdash/f2c4850a5879b483e92bc6bf2b1dd8af to your computer and use it in GitHub Desktop.
Save slashdotdash/f2c4850a5879b483e92bc6bf2b1dd8af to your computer and use it in GitHub Desktop.
Example shopping cart aggregate using Chronik
defmodule Example.Cart do
use Chronik.Aggregate
alias Example.Cart
alias Example.DomainEvents.{CartCreated, ItemsAdded, ItemsRemoved}
defstruct [id: nil, items: %{}]
## Public API
def create(id), do: Aggregate.command(id, {:create, id})
def add_items(id, item_id, quantity), do: Aggregate.command(id, {:add_items, id, item_id, quantity})
def remove_items(id, item_id, quantity), do: Aggregate.command(id, {:remove_items, id, item_id, quantity})
## Cart commands
def handle_command({:create, id}, nil) do
%CartCreated{id: id}
end
def handle_command({:create, id}, _state) do
raise CartExistsError, "Cart already created"
end
def handle_command({:add_items, id, item_id, quantity}, %Cart{}) do
%ItemsAdded{id: id, item_id: item_id, quantity: quantity}
end
def handle_command({:remove_items, id, item_id, quantity}, %Cart{items: items}) do
current_quantity = (items[item_id] || 0)
if current_quantity >= quantity do
%ItemsRemoved{id: id, item_id: item_id, quantity: quantity}
else
raise CartEmptyError, "Cannot remove items from cart #{id}"
end
end
## State transitions
def handle_event(%CartCreated{id: id}, nil) do
%Cart{id: id}
end
def handle_event(%ItemsAdded{item_id: item_id, quantity: quantity}, state) do
current_quantity = (state.items[item_id] || 0) + quantity
%{state | items: Map.put(state.items, item_id, current_quantity)}
end
def handle_event(%ItemsRemoved{item_id: item_id, quantity: quantity}, state) do
current_quantity = (state.items[item_id] || 0) - quantity
%{state | items: Map.put(state.items, item_id, current_quantity)}
end
##
## Exceptions
##
defmodule CartExistsError do
defexception [:message]
end
defmodule CartEmptyError do
defexception [:message]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment