Packages
journey
0.0.5
0.10.58
0.10.57
0.10.56
0.10.55
0.10.54
0.10.53
0.10.52
0.10.51
0.10.50
0.10.49
0.10.48
0.10.47
0.10.46
0.10.45
0.10.44
0.10.43
0.10.41
0.10.40
0.10.39
0.10.38
0.10.37
0.10.36
0.10.35
0.10.34
0.10.33
0.10.32
0.10.31
0.10.30
0.10.29
0.10.28
0.10.27
0.10.26
0.10.25
0.10.24
0.10.23
0.10.22
0.0.9
retired
0.0.8
0.0.7
0.0.6
0.0.5
0.0.3
0.0.2
Journey is a library for defining and running durable workflows with persistence, reliability, and scalability.
Current section
Files
Jump to
Current section
Files
lib/process.ex
defmodule Journey.Process do
@moduledoc """
"""
@enforce_keys [:name, :version, :steps]
defstruct [:name, version: "0.0.0", steps: []]
@typedoc ~S"""
Holds the definition of a process.
## Example: A process for Computing Horoscopes.
iex> _process = %Journey.Process{
...> name: "horoscopes-r-us",
...> version: "0.0.1",
...> steps: [
...> %Journey.Step{name: :first_name},
...> %Journey.Step{name: :birth_month},
...> %Journey.Step{name: :birth_day},
...> %Journey.Step{
...> name: :astrological_sign,
...> func: fn _values ->
...> # Everyone is a Taurus!
...> {:ok, :taurus}
...> end,
...> blocked_by: [
...> birth_month: :provided,
...> birth_day: :provided
...> ]
...> },
...> %Journey.Step{
...> name: :horoscope,
...> func: fn values ->
...> name = values[:first_name].value
...> sign = Atom.to_string(values[:astrological_sign].value)
...> {
...> :ok,
...> "#{name}! You are a #{sign}! Now is the perfect time to smash the racist patriarchy!"
...> }
...> end,
...> blocked_by: [
...> first_name: :provided,
...> astrological_sign: :provided
...> ]
...> }
...> ]
...> }
"""
@type t :: %Journey.Process{name: String.t(), version: String.t(), steps: list(Journey.Step.t())}
defp random_string(length) do
:crypto.strong_rand_bytes(length)
|> Base.encode32(case: :lower, padding: false)
|> binary_part(0, length)
|> String.replace(["+", "/"], "m")
end
@doc ~S"""
Starts a new execution of the process.
## Example
iex> process = %Journey.Process{
...> name: "horoscopes-r-us",
...> version: "0.0.1",
...> steps: [
...> %Journey.Step{name: :first_name},
...> %Journey.Step{name: :birth_month},
...> %Journey.Step{name: :birth_day},
...> %Journey.Step{
...> name: :astrological_sign,
...> func: fn _values ->
...> # Everyone is a Taurus!
...> {:ok, :taurus}
...> end,
...> blocked_by: [
...> birth_month: :provided,
...> birth_day: :provided
...> ]
...> },
...> %Journey.Step{
...> name: :horoscope,
...> func: fn values ->
...> name = values[:first_name].value
...> sign = Atom.to_string(values[:astrological_sign].value)
...> {
...> :ok,
...> "#{name}! You are a #{sign}! Now is the perfect time to smash the racist patriarchy!"
...> }
...> end,
...> blocked_by: [
...> first_name: :provided,
...> astrological_sign: :provided
...> ]
...> }
...> ]
...> }
iex>
iex> # Start a new execution of the process.
iex> execution = Journey.Process.execute(process)
iex>
iex>
iex> {:ok, execution} = Journey.Execution.update_value(execution, :first_name, "Luigi")
iex> {:not_computed, _} = Journey.Execution.read_value(execution, :astrological_sign)
iex> {:ok, execution} = Journey.Execution.update_value(execution, :birth_month, 4)
iex> {:ok, execution} = Journey.Execution.update_value(execution, :birth_day, 29)
iex> :timer.sleep(100) # Give :astrological_sign's function a bit of time to run.
iex> {:computed, :taurus} = execution.execution_id |> Journey.Execution.load!() |> Journey.Execution.read_value(:astrological_sign)
iex> :timer.sleep(100) # Give :horoscope's function a bit of time to run.
iex> {:computed, horoscope} = execution.execution_id |> Journey.Execution.load!() |> Journey.Execution.read_value(:horoscope)
iex> horoscope
"Luigi! You are a taurus! Now is the perfect time to smash the racist patriarchy!"
"""
@spec execute(Journey.Process.t()) :: Journey.Execution.t()
def execute(process) do
process = %{process | steps: [%Journey.Step{name: :started_at}] ++ process.steps}
execution =
%Journey.Execution{
execution_id: random_string(10),
process: process,
values: blank_values(process)
}
|> Journey.ExecutionStore.put()
{:ok, execution} = Journey.Execution.update_value(execution.execution_id, :started_at, System.os_time(:second))
execution
end
defp blank_values(process) do
process
|> Map.get(:steps, [])
|> Enum.reduce(
%{},
fn step, acc ->
acc
|> Map.put_new(step.name, %Journey.Value{name: step.name})
end
)
end
end