Packages

Write simple, event driven applications

Current section

Files

Jump to
fable lib fable.ex
Raw

lib/fable.ex

defmodule Fable do
use Supervisor
@moduledoc """
Handles the mechanics of event sourcing.
## Wishlist
In the future I want to drive the handler children exclusively off of the
`stream_cursors` database table.
"""
def create_handler(repo, name, module, initial_state) do
last_event_id =
case module.start_at(initial_state) do
:origin ->
-1
:head ->
repo.aggregate(__MODULE__.Event, :max, :id)
n when is_integer(n) ->
n
end
%__MODULE__.EventHandler{
last_event_id: last_event_id,
name: name,
module: module,
state: initial_state
}
|> repo.insert()
end
def start_link(opts) do
opts = Map.new(opts)
config = __MODULE__.Config.new(opts)
config.repo || raise "Ecto Repo required!"
Supervisor.start_link(__MODULE__, config, [])
end
@doc false
def via(registry, name) do
{:via, Registry, {registry, name}}
end
@doc false
def init(%{registry: registry} = config) do
notifications_name = via(registry, Notifications)
children = [
{Registry, keys: :unique, name: registry},
notifications_child(config, notifications_name),
{DynamicSupervisor, strategy: :one_for_one, name: via(registry, HandlerSupervisor)},
{__MODULE__.HandlerInitializer, config}
]
Supervisor.init(children, strategy: :rest_for_one)
end
defp notifications_child(repo, name) do
config =
repo.config()
|> Keyword.put(:name, name)
|> Keyword.put(:pool_size, 1)
%{
id: Postgrex.Notifications,
start: {Postgrex.Notifications, :start_link, [config]}
}
end
end