Current section

Files

Jump to
incident lib incident projection_store in_memory_adapter.ex
Raw

lib/incident/projection_store/in_memory_adapter.ex

defmodule Incident.ProjectionStore.InMemory.Adapter do
@moduledoc """
Implements an in-memory Projection Store using Agents.
"""
@behaviour Incident.ProjectionStore.Adapter
use Agent
@spec start_link(keyword) :: GenServer.on_start()
def start_link(opts \\ []) do
initial_state = Keyword.get(opts, :initial_state, %{})
Agent.start_link(fn -> initial_state end, name: __MODULE__)
end
@impl true
# credo:disable-for-this-file
def project(projection, %{aggregate_id: aggregate_id} = data) do
Agent.update(__MODULE__, fn state ->
update_in(state, [projection], fn projections ->
case Enum.find(projections, &(&1.aggregate_id == aggregate_id)) do
nil ->
[data] ++ projections
_ ->
Enum.reduce(projections, [], fn record, acc ->
case record.aggregate_id == aggregate_id do
true -> [Map.merge(record, data)] ++ acc
false -> [record] ++ acc
end
end)
end
end)
end)
{:ok, data}
end
@impl true
def all(projection) do
Agent.get(__MODULE__, fn state ->
Map.get(state, projection)
end)
end
@impl true
def get(projection, aggregate_id) do
projection
|> all()
|> Enum.find(&(&1.aggregate_id == aggregate_id))
end
end