Packages
reactor
0.3.2
1.0.2
1.0.1
1.0.0
0.17.0
0.16.0
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
An asynchronous, graph-based execution engine
Current section
Files
Jump to
Current section
Files
lib/reactor/dsl/switch.ex
defmodule Reactor.Dsl.Switch do
@moduledoc """
The `switch` DSL entity struct.
See `d:Reactor.switch`.
"""
defstruct __identifier__: nil,
allow_async?: true,
default: nil,
matches: [],
name: nil,
on: nil
alias Reactor.{
Dsl.Build,
Dsl.Switch,
Dsl.Switch.Default,
Dsl.Switch.Match,
Step,
Template
}
@type t :: %Switch{
__identifier__: any,
allow_async?: boolean,
default: nil | Default.t(),
matches: [Match.t()],
name: atom,
on: Template.Input.t() | Template.Result.t() | Template.Value.t()
}
defimpl Build do
import Reactor.Utils
alias Reactor.{Argument, Builder, Planner}
alias Spark.{Dsl.Verifier, Error.DslError}
def build(switch, reactor) do
with {:ok, matches} <- build_matches(switch, reactor),
{:ok, default} <- build_default(switch, reactor) do
Builder.add_step(
reactor,
switch.name,
{Step.Switch,
on: :value, matches: matches, default: default, allow_async?: switch.allow_async?},
[%Argument{name: :value, source: switch.on}],
async?: switch.allow_async?,
max_retries: 0,
ref: :step_name
)
end
end
def verify(switch, dsl_state) when switch.matches == [] do
{:error,
DslError.exception(
module: Verifier.get_persisted(dsl_state, :module),
path: [:reactor, :switch, :matches?, switch.name],
message: "No match branches provided for switch"
)}
end
def verify(_switch, _dsl_state), do: :ok
def transform(_switch, dsl_state), do: {:ok, dsl_state}
defp build_matches(switch, reactor) do
map_while_ok(switch.matches, &build_match(&1, switch, reactor), true)
end
defp build_match(match, switch, reactor) do
with {:ok, reactor} <- build_steps(match.steps, reactor),
{:ok, reactor} <- maybe_build_return_step(match.return, switch, reactor),
{:ok, _} <- Planner.plan(reactor) do
{:ok, {match.predicate, reactor.steps}}
end
end
defp build_default(switch, _reactor) when is_nil(switch.default), do: {:ok, []}
defp build_default(switch, reactor) do
with {:ok, reactor} <- build_steps(switch.default.steps, reactor),
{:ok, reactor} <- maybe_build_return_step(switch.default.return, switch, reactor),
{:ok, _} <- Planner.plan(reactor) do
{:ok, reactor.steps}
end
end
defp build_steps(steps, reactor), do: reduce_while_ok(steps, reactor, &Build.build/2)
defp maybe_build_return_step(nil, _, reactor), do: {:ok, reactor}
defp maybe_build_return_step(return_name, switch, reactor) do
Builder.add_step(
reactor,
switch.name,
{Step.ReturnArgument, argument: :value},
[Argument.from_result(:value, return_name)],
async?: switch.allow_async?,
max_retries: 0,
ref: :step_name
)
end
end
end