Packages
ash
1.6.1
3.29.3
3.29.2
3.29.1
3.29.0
3.28.0
3.27.8
3.27.7
3.27.6
3.27.5
3.27.4
3.27.3
3.27.2
3.27.1
3.27.0
3.26.0
3.25.2
3.25.1
3.25.0
retired
3.24.7
3.24.6
3.24.5
3.24.4
3.24.3
3.24.2
3.24.1
3.24.0
3.23.1
3.23.0
3.22.2
3.22.1
3.22.0
3.21.3
3.21.2
3.21.1
3.21.0
3.20.0
3.19.3
3.19.2
3.19.1
3.19.0
3.18.0
3.17.1
3.17.0
3.16.0
3.15.0
3.14.1
3.14.0
retired
3.13.2
3.13.1
3.13.0
3.12.0
3.11.3
3.11.2
3.11.1
3.11.0
3.10.1
3.10.0
3.9.0
3.8.0
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
retired
3.6.3
retired
3.6.2
3.6.1
3.6.0
3.5.43
3.5.42
3.5.41
3.5.40
3.5.39
3.5.38
3.5.37
3.5.36
3.5.35
3.5.34
3.5.33
3.5.32
3.5.31
3.5.30
3.5.29
3.5.28
3.5.27
3.5.26
3.5.25
3.5.24
3.5.23
3.5.22
3.5.21
3.5.20
3.5.19
3.5.18
3.5.17
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.10
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.4.74
retired
3.4.73
3.4.72
3.4.71
3.4.70
3.4.69
3.4.68
3.4.67
3.4.66
3.4.65
3.4.64
3.4.63
3.4.62
3.4.61
3.4.60
3.4.59
3.4.58
3.4.57
3.4.56
3.4.55
3.4.54
3.4.53
3.4.52
3.4.51
3.4.50
3.4.49
3.4.48
3.4.47
3.4.46
3.4.45
3.4.44
3.4.43
3.4.42
3.4.41
3.4.40
3.4.39
3.4.38
3.4.37
3.4.36
3.4.35
3.4.34
3.4.33
3.4.32
3.4.31
3.4.30
3.4.29
3.4.28
3.4.27
3.4.26
3.4.25
3.4.24
3.4.23
3.4.22
3.4.21
3.4.20
3.4.19
3.4.18
3.4.17
3.4.16
3.4.15
3.4.14
3.4.13
3.4.12
3.4.11
3.4.10
3.4.9
3.4.8
3.4.7
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.3
3.3.2
3.3.1
3.3.0
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.16
3.0.15
3.0.14
3.0.13
3.0.12
3.0.11
3.0.10
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.46
3.0.0-rc.45
3.0.0-rc.44
3.0.0-rc.43
3.0.0-rc.42
3.0.0-rc.41
3.0.0-rc.40
3.0.0-rc.39
3.0.0-rc.38
3.0.0-rc.37
3.0.0-rc.36
3.0.0-rc.35
3.0.0-rc.34
3.0.0-rc.33
3.0.0-rc.32
3.0.0-rc.31
3.0.0-rc.29
3.0.0-rc.28
3.0.0-rc.27
3.0.0-rc.26
3.0.0-rc.25
3.0.0-rc.24
3.0.0-rc.23
3.0.0-rc.22
3.0.0-rc.21
3.0.0-rc.20
3.0.0-rc.19
3.0.0-rc.18
3.0.0-rc.17
3.0.0-rc.16
3.0.0-rc.15
3.0.0-rc.14
3.0.0-rc.13
3.0.0-rc.12
3.0.0-rc.11
3.0.0-rc.10
3.0.0-rc.9
3.0.0-rc.8
3.0.0-rc.7
3.0.0-rc.6
3.0.0-rc.5
3.0.0-rc.4
3.0.0-rc.3
3.0.0-rc.1
3.0.0-rc.0
2.21.15
2.21.14
2.21.13
2.21.12
2.21.11
2.21.10
2.21.9
2.21.8
2.21.7
2.21.6
2.21.5
2.21.4
2.21.3
2.21.2
2.21.1
2.21.0
2.20.3
2.20.2
2.20.1
2.20.0
2.19.14
2.19.13
2.19.12
2.19.11
2.19.10
2.19.9
2.19.8
2.19.7
2.19.6
2.19.5
2.19.4
2.19.3
retired
2.19.2
retired
2.19.1
retired
2.19.0
retired
2.18.2
2.18.1
2.18.0
2.17.24
2.17.23
2.17.22
2.17.21
2.17.20
2.17.19
2.17.18
2.17.17
2.17.16
2.17.15
2.17.14
2.17.13
2.17.12
2.17.11
2.17.10
2.17.9
2.17.8
2.17.7
2.17.6
2.17.5
2.17.4
2.17.3
2.17.2
2.17.1
2.17.0
2.16.1
2.16.0
2.15.20
2.15.19
2.15.18
2.15.17
2.15.16
2.15.15
2.15.14
2.15.13
2.15.12
2.15.11
2.15.10
2.15.9
2.15.8
2.15.7
2.15.6
2.15.5
2.15.4
2.15.2
2.15.1
2.15.0
2.14.21
2.14.20
2.14.19
2.14.18
2.14.17
2.14.16
2.14.15
2.14.14
2.14.13
2.14.12
2.14.11
2.14.10
2.14.9
2.14.8
2.14.7
2.14.6
2.14.5
2.14.4
2.14.3
2.14.2
2.14.1
2.14.0
2.13.4
retired
2.13.3
2.13.2
2.13.1
2.13.0
2.12.1
2.12.0
2.11.11
2.11.10
2.11.9
2.11.8
2.11.7
2.11.6
2.11.5
2.11.4
2.11.3
2.11.2
2.11.1
2.11.0
2.11.0-rc.3
2.11.0-rc.2
2.11.0-rc.1
2.11.0-rc.0
2.10.2
2.10.1
2.10.0
2.9.29
2.9.28
2.9.27
2.9.26
2.9.25
2.9.24
2.9.23
2.9.22
2.9.21
2.9.20
2.9.19
2.9.18
2.9.17
2.9.16
2.9.15
2.9.14
2.9.13
2.9.12
2.9.11
2.9.10
2.9.9
2.9.8
2.9.7
2.9.6
2.9.5
2.9.4
2.9.3
2.9.2
2.9.1
2.9.0
2.8.1
2.8.0
2.7.1
2.7.0
2.6.31
2.6.30
2.6.29
2.6.28
2.6.27
2.6.26
2.6.25
2.6.24
2.6.23
2.6.22
2.6.21
2.6.20
2.6.19
2.6.18
2.6.17
2.6.16
2.6.15
2.6.14
2.6.13
2.6.11
2.6.10
2.6.9
2.6.8
2.6.7
2.6.6
2.6.5
2.6.4
2.6.3
2.6.2
2.6.1
2.6.0
2.5.16
2.5.15
2.5.14
2.5.13
2.5.12
2.5.11
2.5.10
2.5.9
2.5.8
2.5.7
2.5.6
2.5.5
2.5.4
2.5.3
2.5.2
2.5.1
2.5.0
2.5.0-rc.6
2.5.0-rc.5
2.5.0-rc.4
2.5.0-rc.3
2.5.0-rc.2
2.5.0-rc.1
2.5.0-rc.0
2.4.30
2.4.29
2.4.28
2.4.27
2.4.26
2.4.25
2.4.24
2.4.23
2.4.22
2.4.21
2.4.20
2.4.19
2.4.18
2.4.17
2.4.16
2.4.15
2.4.14
2.4.13
2.4.12
2.4.11
2.4.10
2.4.9
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
2.0.0-rc.15
2.0.0-rc.14
2.0.0-rc.13
2.0.0-rc.12
2.0.0-rc.11
2.0.0-rc.10
2.0.0-rc.9
2.0.0-rc.8
2.0.0-rc.7
2.0.0-rc.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-pre.8
2.0.0-pre.7
2.0.0-pre.6
2.0.0-pre.5
2.0.0-pre.4
2.0.0-pre.3
2.0.0-pre.2
2.0.0-pre.1
2.0.0-pre.0
1.53.3
1.53.2
1.53.0
1.52.0-rc.22
1.52.0-rc.21
1.52.0-rc.20
1.52.0-rc.19
1.52.0-rc.18
1.52.0-rc.17
1.52.0-rc.16
1.52.0-rc.15
1.52.0-rc.14
1.52.0-rc.13
1.52.0-rc.12
1.52.0-rc.11
1.52.0-rc.10
1.52.0-rc.9
1.52.0-rc.8
1.52.0-rc.7
1.52.0-rc.6
1.52.0-rc.5
1.52.0-rc.4
1.52.0-rc.3
1.52.0-rc.2
1.52.0-rc.1
1.52.0-rc.0
1.51.2
1.51.1
retired
1.51.0
1.50.21
1.50.20
1.50.19
1.50.18
1.50.17
1.50.16
1.50.15
1.50.14
1.50.13
1.50.12
1.50.11
1.50.10
1.50.9
1.50.8
1.50.7
1.50.6
1.50.5
1.50.4
1.50.3
1.50.2
1.50.1
1.50.0
1.49.0
1.48.0-rc.30
1.48.0-rc.29
1.48.0-rc.28
1.48.0-rc.27
1.48.0-rc.26
1.48.0-rc.25
1.48.0-rc.24
1.48.0-rc.23
1.48.0-rc.22
1.48.0-rc.21
1.48.0-rc.20
1.48.0-rc.19
1.48.0-rc.18
1.48.0-rc.17
1.48.0-rc.16
1.48.0-rc.15
1.48.0-rc.14
1.48.0-rc.13
1.48.0-rc.12
1.48.0-rc.11
1.48.0-rc.10
1.48.0-rc.9
1.48.0-rc.8
1.48.0-rc.7
1.48.0-rc.6
1.48.0-rc.5
1.48.0-rc.4
1.48.0-rc.3
1.48.0-rc.2
1.48.0-rc.1
1.48.0-rc.0
1.47.12
1.47.11
1.47.10
1.47.9
1.47.8
1.47.7
1.47.6
1.47.5
1.47.4
1.47.3
1.47.2
1.47.1
1.47.0
1.46.13
1.46.12
1.46.11
1.46.10
1.46.9
1.46.8
1.46.7
1.46.6
1.46.5
1.46.4
1.46.3
1.46.2
1.46.1
1.46.0
1.45.0-rc9
1.45.0-rc8
1.45.0-rc7
1.45.0-rc6
1.45.0-rc5
1.45.0-rc4
1.45.0-rc3
1.45.0-rc20
1.45.0-rc2
1.45.0-rc19
1.45.0-rc18
1.45.0-rc17
1.45.0-rc16
1.45.0-rc15
1.45.0-rc14
1.45.0-rc13
1.45.0-rc12
1.45.0-rc11
1.45.0-rc10
1.45.0-rc1
1.45.0-rc0
1.44.13
1.44.12
1.44.11
1.44.10
1.44.9
1.44.8
1.44.7
1.44.6
1.44.5
1.44.4
1.44.3
1.44.2
1.44.1
1.44.0
1.43.12
1.43.11
1.43.10
1.43.9
1.43.8
1.43.7
1.43.6
1.43.5
1.43.4
1.43.3
1.43.2
1.43.1
1.43.0
1.42.0
1.41.12
1.41.11
1.41.10
1.41.9
1.41.8
1.41.7
1.41.6
1.41.5
1.41.4
1.41.3
1.41.2
1.41.1
1.41.0
1.40.0
1.39.7
1.39.6
1.39.5
1.39.4
1.39.3
1.39.2
1.39.1
1.39.0
1.38.0
1.37.2
1.37.1
1.37.0
1.36.22
1.36.21
1.36.19
1.36.18
1.36.17
1.36.16
1.36.15
1.36.14
1.36.13
1.36.12
1.36.11
1.36.10
1.36.9
1.36.8
1.36.7
1.36.6
1.36.5
1.36.4
1.36.3
1.36.2
1.36.0
1.35.1
1.35.0
1.34.9
1.34.8
1.34.7
1.34.6
1.34.5
1.34.4
1.34.3
1.34.2
1.34.1
1.34.0
1.33.0
1.32.2
1.32.1
1.32.0
1.31.1
1.31.0
1.30.2
1.30.1
1.29.0-rc1
1.29.0-rc0
1.28.1
1.28.0
1.27.1
1.27.0
1.26.13
1.26.12
1.26.11
1.26.10
1.26.9
1.26.8
1.26.7
1.26.6
1.26.5
1.26.4
1.26.2
1.26.1
1.26.0
1.25.8
1.25.7
1.25.6
1.25.5
1.25.4
1.25.3
1.25.2
1.25.1
1.25.0
1.24.2
1.24.1
1.24.0
1.23.3
1.23.2
1.23.1
1.23.0
1.22.1
1.22.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.1
1.18.0
1.17.1
1.17.0
1.16.2
1.15.1
1.15.0
1.14.0
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.1
1.11.0
1.10.0
1.9.0
1.8.0
1.7.0
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.1
1.4.0
1.3.1
1.3.0
1.2.1
1.2.0
1.1.3
1.1.2
1.1.0
1.0.3
1.0.2
1.0.1
1.0.0
0.13.1
0.13.0
0.12.0
0.10.0
0.9.1
0.9.0
0.8.0
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.9
0.1.8
0.1.3
0.1.1
0.1.0
A declarative, extensible framework for building Elixir applications.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash/engine/runner.ex
defmodule Ash.Engine.Runner do
@moduledoc false
defstruct [
:engine_pid,
notified_of_complete?: false,
requests: [],
errors: [],
data: %{},
pid_info: %{},
dependencies: %{},
verbose?: false
]
alias Ash.Engine
alias Ash.Engine.{Request, RequestHandler}
alias Ash.Error.Framework.SynchronousEngineStuck
require Logger
def run(requests, verbose?, engine_pid \\ nil, pid_info \\ %{}) do
state = %__MODULE__{
requests: requests,
verbose?: verbose?,
engine_pid: engine_pid,
pid_info: pid_info
}
log(state, "Synchronous engine starting - #{Enum.map_join(requests, ", ", & &1.name)}")
new_state = run_to_completion(state)
Enum.reduce(new_state.requests, new_state, &add_data(&2, &1.path, &1.data))
end
def run_to_completion(state) do
if Enum.all?(state.requests, &(&1.state in [:complete, :error])) do
# This allows for publishing any dependencies
new_state = run_iteration(state)
if new_state.engine_pid do
new_state =
if new_state.notified_of_complete? do
new_state
else
log(new_state, "notifying engine of local request completion")
GenServer.cast(new_state.engine_pid, :local_requests_complete)
%{new_state | notified_of_complete?: true}
end
wait_for_engine(new_state, true)
else
log(state, "Synchronous engine complete.")
new_state
end
else
case run_iteration(state) do
new_state when new_state == state ->
if new_state.engine_pid do
wait_for_engine(new_state, false)
else
log(state, "Synchronous engine stuck:\n\n#{stuck_report(state)}")
add_error(new_state, :__engine__, SynchronousEngineStuck.exception([]))
end
new_state ->
run_to_completion(new_state)
end
end
end
defp stuck_report(state) do
Enum.map_join(state.requests, "\n", fn request ->
if request.state in [:complete, :error] do
to_string(request.name) <> ": " <> "#{inspect(request.state)}"
else
case Request.next(request) do
{:wait, _, _, []} ->
to_string(request.name) <> ": Waiting on nothing in state #{inspect(request.state)}"
{:wait, _, _, dependencies} ->
to_string(request.name) <> ": Waiting on #{dependency_names(dependencies, state)}"
_other ->
to_string(request.name) <> ": Not waiting, not complete"
end
end
end)
end
defp dependency_names(dependencies, state) do
Enum.map_join(dependencies, ", ", fn dependency ->
path = :lists.droplast(dependency)
field = List.last(dependency)
request = Enum.find(state.requests, &(&1.path == path))
request.name <> ": " <> to_string(field)
end)
end
defp wait_for_engine(state, complete?) do
engine_pid = state.engine_pid
log(state, "waiting for engine")
receive do
{:"$gen_cast", message} ->
log(state, "Received #{inspect(message)}")
message
|> fake_handle_cast(state)
|> run_to_completion()
{:data, path, data} ->
state
|> add_data(path, data)
|> wait_for_engine(complete?)
{:DOWN, _, _, ^engine_pid, {:shutdown, %{errored_requests: []} = engine_state}} ->
log(state, "Engine complete")
handle_completion(state, engine_state, complete?, false)
{:DOWN, _, _, ^engine_pid, {:shutdown, engine_state}} ->
log(state, "Engine complete")
handle_completion(state, engine_state, complete?, true)
end
end
defp handle_completion(state, engine_state, complete?, engine_error?) do
new_state =
if complete? do
if engine_error? do
log(engine_state, "Engine shutdown error")
else
log(engine_state, "Engine complete, graceful shutdown")
end
state
else
run_to_completion(state)
end
add_engine_state(new_state, engine_state)
end
defp add_engine_state(state, engine_state) do
new_state = %{state | errors: engine_state.errors ++ state.errors}
log(state, "waiting for engine data")
receive_data(new_state)
end
defp receive_data(state) do
receive do
{:data, path, data} ->
state
|> add_data(path, data)
|> receive_data()
after
0 ->
state
end
end
defp fake_handle_cast({:wont_receive, receiver_path, path, field}, state) do
request = Enum.find(state.requests, &(&1.path == receiver_path))
case Request.wont_receive(request, path, field) do
{:stop, :dependency_failed, new_request} ->
replace_request(state, %{new_request | state: :error})
end
end
defp fake_handle_cast({:send_field, receiver_path, pid, dep}, state) do
log(state, "notifying #{inspect(receiver_path)} of #{inspect(dep)}")
path = :lists.droplast(dep)
field = List.last(dep)
request = Enum.find(state.requests, &(&1.path == path))
case Request.send_field(request, receiver_path, field) do
{:waiting, new_request, notifications, dependencies} ->
new_dependencies = build_dependencies(new_request, dependencies)
{new_state, new_notifications} =
state
|> replace_request(new_request)
|> store_dependencies(new_dependencies)
notify(new_state, notifications ++ new_notifications)
{:ok, new_request, notifications} ->
state
|> replace_request(new_request)
|> notify(notifications)
{:error, error, new_request} ->
Engine.send_wont_receive(pid, receiver_path, new_request.path, field)
state
|> add_error(new_request.path, error)
|> replace_request(%{new_request | state: :error})
end
end
defp fake_handle_cast({:field_value, receiver_path, request_path, field, value}, state) do
receiver_path =
case receiver_path do
{_, path} -> path
path -> path
end
request = Enum.find(state.requests, &(&1.path == receiver_path))
case Request.receive_field(request, request_path, field, value) do
{:continue, new_request} ->
replace_request(state, new_request)
end
end
defp build_dependencies(request, dependencies) do
Enum.map(dependencies, fn dep ->
{request.path, dep}
end)
end
defp run_iteration(state) do
{new_state, notifications, dependencies} =
Enum.reduce(state.requests, {state, [], []}, fn request,
{state, notifications, dependencies} ->
{new_state, new_notifications, new_dependencies} = fully_advance_request(state, request)
{new_state, notifications ++ new_notifications, new_dependencies ++ dependencies}
end)
store_dependencies(new_state, dependencies, notifications)
end
defp store_dependencies(state, dependencies, notifications \\ []) do
log(state, "Storing generated dependencies")
{state, notifications, more_dependencies} =
dependencies
|> Enum.uniq()
|> Enum.reduce({state, notifications, []}, fn {request_path, dep},
{state, notifications, dependencies} ->
request = Enum.find(state.requests, &(&1.path == request_path))
path = :lists.droplast(dep)
field = List.last(dep)
case Enum.find(state.requests, &(&1.path == path)) do
nil ->
pid = Map.get(state.pid_info, path)
GenServer.cast(pid, {:send_field, request_path, self(), dep})
{state, notifications, dependencies}
depended_on_request ->
if request.error? || depended_on_request.error? do
{state, notifications, dependencies}
else
notify_local_request(
state,
notifications,
dependencies,
depended_on_request,
request,
field
)
end
end
end)
case more_dependencies do
[] ->
notify(state, notifications)
more_dependencies ->
store_dependencies(state, more_dependencies, notifications)
end
end
defp notify_local_request(
state,
notifications,
dependencies,
depended_on_request,
request,
field
) do
case Request.send_field(depended_on_request, request.path, field) do
{:ok, new_request, new_notifications} ->
{replace_request(state, new_request), notifications ++ new_notifications, dependencies}
{:waiting, new_request, new_notifications, new_dependencies} ->
new_dependencies = build_dependencies(new_request, new_dependencies)
new_state = replace_request(state, new_request)
{new_state, notifications ++ new_notifications, new_dependencies ++ dependencies}
{:error, error, new_request} ->
new_state =
state
|> replace_request(%{new_request | state: :error, error?: true})
|> add_error(new_request.path, error)
|> replace_request(%{new_request | state: :error, error?: true})
{new_state, notifications, dependencies}
end
end
defp notify(state, notifications) do
log(state, "sending/updating requests with notifications")
notifications
|> List.wrap()
|> Enum.uniq()
|> Enum.reduce(state, fn {receiver_path, request_path, field, value}, state ->
case Enum.find(state.requests, &(&1.path == receiver_path)) do
nil ->
pid = Map.get(state.pid_info, receiver_path)
RequestHandler.send_field_value(
pid,
receiver_path,
request_path,
field,
value
)
state
receiver_request ->
{:continue, new_request} =
Request.receive_field(receiver_request, request_path, field, value)
replace_request(state, new_request)
end
end)
end
defp replace_request(state, request) do
%{
state
| requests:
Enum.map(state.requests, fn existing_request ->
if existing_request.id == request.id do
request
else
existing_request
end
end)
}
end
defp fully_advance_request(state, request) do
case advance_request(request) do
{:ok, new_request, notifications, dependencies} ->
new_state = replace_request(state, new_request)
new_dependencies = build_dependencies(new_request, dependencies)
{new_state, notifications, new_dependencies}
{:error, error, new_request} ->
new_state =
state
|> add_error(new_request.path, error)
|> replace_request(%{new_request | state: :error})
{new_state, [], []}
end
end
defp advance_request(%{state: :error} = request) do
{:ok, request, [], []}
end
defp advance_request(request) do
case Request.next(request) do
{:already_complete, new_request, new_notifications, new_dependencies} ->
{:ok, new_request, new_notifications, new_dependencies}
{:complete, new_request, new_notifications, new_dependencies} ->
{:ok, new_request, new_notifications, new_dependencies}
{:continue, new_request, new_notifications} ->
{:ok, new_request, new_notifications, []}
{:error, error, new_request} ->
{:error, error, new_request}
{:wait, new_request, new_notifications, new_dependencies} ->
{:ok, new_request, new_notifications, new_dependencies}
end
end
defp add_data(state, path, data) do
%{
state
| data: Engine.put_nested_key(state.data, path, data)
}
end
defp add_error(state, path, error) do
path = List.wrap(path)
error = Map.put(Ash.Error.to_ash_error(error), :path, path)
if error in state.errors do
state
else
%{state | errors: [Map.put(error, :path, path) | state.errors]}
end
end
defp log(request, message, level \\ :debug)
defp log(%{verbose?: true}, message, level) do
Logger.log(level, "Runner: " <> message)
end
defp log(_, _, _) do
false
end
end