Packages
reactor
0.14.0
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/step/map/mermaid.ex
defmodule Reactor.Step.Map.Mermaid do
@moduledoc """
Mermaid rendering for `map` steps.
"""
alias Reactor.{Argument, Builder, Mermaid, Template}
import Reactor.Utils
import Mermaid.Utils
require Argument
@doc false
def to_mermaid(%{impl: {Reactor.Step.Map, opts}} = step, options) do
steps = Keyword.get(opts, :steps, [])
with {:ok, reactor} <- build_nested_reactor(step.arguments, step.name, steps, opts[:return]),
{:ok, sub_graph} <- Mermaid.Reactor.to_mermaid(reactor, options),
{:ok, node} <- describe_step(step, options) do
inner_return_id = mermaid_id(reactor.id, :return)
links =
reactor.inputs
|> Enum.map(fn input ->
[node.id, "-->", mermaid_id({reactor.id, input}, :input), "\n"]
end)
|> Enum.concat([inner_return_id, "-->", node.id, "\n"])
{:ok, %{node | post: [sub_graph, node.post, links]}}
end
end
defp build_nested_reactor(arguments, name, steps, return) do
reactor = Builder.new({__MODULE__, name})
with {:ok, reactor} <- build_inputs(reactor, arguments),
{:ok, reactor} <- build_steps(reactor, steps) do
{:ok, %{reactor | return: return}}
end
end
defp build_inputs(reactor, arguments) do
arguments
|> map_while_ok(&Argument.Build.build/1)
|> and_then(&{:ok, List.flatten(&1)})
|> and_then(fn arguments ->
reduce_while_ok(arguments, reactor, &Builder.add_input(&2, &1.name))
end)
end
defp build_steps(reactor, steps) do
steps =
Enum.map(steps, fn step ->
arguments =
Enum.map(step.arguments, fn
argument when Argument.is_from_element(argument) ->
%{argument | source: %Template.Input{name: :source}}
argument ->
argument
end)
%{step | arguments: arguments}
end)
{:ok, %{reactor | steps: Enum.concat(steps, reactor.steps)}}
end
defp describe_step(%{impl: {module, _opts}} = step, options) do
id = mermaid_id({options[:reactor_id], step.name}, :step)
content =
if options[:describe?] do
[
id,
"[\"`**",
md_escape(name(step.name)),
" \\(",
inspect(module),
"\\)**",
if(step.description, do: ["\n", md_escape(step.description)], else: []),
"`\"]\n"
]
else
[
id,
"[\"",
name(step.name),
"(",
inspect(module),
")\"]\n"
]
end
{:ok, %Mermaid.Node{id: id, pre: content}}
end
end