Current section
Files
Jump to
Current section
Files
lib/grains.ex
defmodule Grains do
@moduledoc """
Grains describes data flow as a graph with interchangeable parts.
To accomplish that grains divides the graph (`Recipe`) from the
implementation of the nodes (`Grains`).
Together these parts can be used to make a `Bread` which describes
how the graph translates to processes.
Each process has a symbolic short name, which is resolved
to the registered name of the process via a map (`%Bread{}.process_map`).
"""
alias Grains.Bread
alias Grains.Recipe
alias Grains.Supervisor
defstruct [:map]
@doc """
This function describes the default implementations
for auxiliary grains, for example the periodic timer.
Currently these default grains are provided:
iex> Grains.default_grains()
%{periodic: Grains.Timer}
"""
def default_grains() do
%{
periodic: Grains.Timer
}
end
def new(map) do
%__MODULE__{map: map}
end
@doc """
Merges to grain maps, works the same as Map.merge/2.
Seconds grains override first in case of a name clash.
"""
def merge(%__MODULE__{map: a}, %__MODULE__{map: b}) do
a
|> Map.merge(b)
|> new()
end
defdelegate new_recipe(name, new), to: Grains.Recipe, as: :new
defdelegate merge_recipes(name, a, b), to: Grains.Recipe, as: :merge
defdelegate start_supervised(recipe, grains, default_grains \\ default_grains()), to: Grains.Supervisor, as: :start_link
@spec make_name(Recipe.t, atom, atom) :: atom
def make_name(recipe = %Recipe{}, bread_id, short_name) do
[recipe.name, bread_id, short_name] |> Module.concat()
end
@spec make_bread_name(Recipe.t, atom()) :: atom()
def make_bread_name(recipe = %Recipe{}, bread_id) do
[recipe.name, bread_id] |> Module.concat()
end
@spec get_name(Supervisor.t, atom) :: atom()
def get_name(supervisor, short_name) do
Module.concat([Supervisor.get_root_name(supervisor), short_name])
end
@spec concat_name(Bread.t, atom) :: atom
def concat_name(bread = %Bread{}, grain) do
Module.concat([bread.name, grain])
end
@doc """
Description of a periodic grain.
"""
def periodic(grain, period, opts \\ %{with_timestamps: false}) do
{:periodic, grain, Map.put(opts, :period, period)}
end
end