Skip to content

Instantly share code, notes, and snippets.

@orodio
Last active September 4, 2018 16:10
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save orodio/9ca6f87be23504e82810 to your computer and use it in GitHub Desktop.
Actor Model Pattern in elixir
defmodule BankAccount do
def start do
await
end
def await, do: await([])
def await events do
receive do
event = { :deposit, _amount } -> events = [ event | events ]
event = { :withdraw, _amount } -> events = [ event | events ]
{ :check_balance, pid } -> send_balance pid, events
end
await events
end
defp send_balance pid, events do
Process.send pid, {:balance, current_balance(events)}, []
end
defp current_balance events do
Enum.reduce events, 0, &amount_reducer/2
end
defp amount_reducer({:deposit, amount}, acc), do: acc + amount
defp amount_reducer({:withdraw, amount}, acc), do: acc - amount
defp amount_reducer({_type, amount}, acc), do: acc
end
defmodule BankAccountTest do
use ExUnit.Case
test "BankAccounts start with a balance of 0" do
init_account
|> send_message({:check_balance, self})
assert_receive { :balance, 0 }
end
test "you can deposit into a bank account" do
init_account
|> send_message({ :deposit, 20 })
|> send_message({ :check_balance, self })
assert_receive { :balance, 20 }
end
test "you can withdraw from a bank account" do
init_account
|> send_message({ :deposit, 20 })
|> send_message({ :withdraw, 10 })
|> send_message({ :check_balance, self })
assert_receive { :balance, 10 }
end
test "calc_balance figures out the balance correctly" do
events = [deposit: 50, withdraw: 30, deposit: 20, withdraw: 10]
assert BankAccount.calc_balance(events) == 30
end
test "send_balance sends the correct balance to the correct pid" do
events = [deposit: 50, withdraw: 30, deposit: 20, withdraw: 10]
BankAccount.send_balance events, self
assert_receive { :balance, 30 }
end
### Private Helpers
defp init_account do
spawn BankAccount, :start, []
end
defp send_message(pid, message) do
Process.send pid, message, []
pid
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment