Current section

Files

Jump to
reactor lib reactor error.ex
Raw

lib/reactor/error.ex

defmodule Reactor.Error do
@moduledoc """
Uses `splode` to manage various classes of error.
"""
use Splode,
error_classes: [
reactor: Reactor.Error.Internal,
invalid: Reactor.Error.Invalid,
unknown: Reactor.Error.Unknown,
validation: Reactor.Error.Validation
],
unknown_error: Reactor.Error.Unknown.UnknownError
@doc "Convenience wrapper around `use Splode.Error`"
@spec __using__(keyword) :: Macro.output()
defmacro __using__(opts) do
quote do
use Splode.Error, unquote(opts)
import Reactor.Error.Utils
import Reactor.Utils
end
end
@doc """
Recursively searches through nested reactor errors for the first instance of
the provided module.
"""
@spec fetch_error(Exception.t(), module) :: {:ok, Exception.t()} | :error
def fetch_error(error, module) when is_exception(error, module), do: {:ok, error}
def fetch_error(error, module) when is_list(error.errors) do
Enum.reduce_while(error.errors, :error, fn error, :error ->
case fetch_error(error, module) do
{:ok, error} -> {:halt, {:ok, error}}
:error -> {:cont, :error}
end
end)
end
def fetch_error(error, module) when is_exception(error.error),
do: fetch_error(error.error, module)
def fetch_error(_error, _module), do: :error
@doc """
Recursively searches through nested reactor errors and returns any errors
which match the provided module name.
"""
@spec find_errors(Exception.t(), module) :: [Exception.t()]
def find_errors(error, module) when is_exception(error, module), do: [error]
def find_errors(error, module) when is_list(error.errors) do
Enum.flat_map(error.errors, &find_errors(&1, module))
end
def find_errors(error, module) when is_exception(error.error),
do: find_errors(error.error, module)
def find_errors(_error, _module), do: []
end