Current section
Files
Jump to
Current section
Files
lib/errors/effect_error.ex
defmodule Funx.Errors.EffectError do
@moduledoc """
[](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2FJKWA%2Ffunx%2Fblob%2Fmain%2Flivebooks%2Ferrors%2Feffect_error.livemd)
Represents a system-level failure in an effectful computation.
`EffectError` is raised or returned when a failure occurs during the execution
of an `Effect` stage, such as `map`, `bind`, or `ap`. It is not meant for user-facing
validation, but rather for internal tracing, telemetry, and diagnostics.
## Fields
* `stage` – the name of the effect stage where the error occurred (`:map`, `:bind`, `:ap`, etc.)
* `reason` – the term (often an exception) that caused the failure
This error implements the `Exception`, `String.Chars`, and `Funx.Summarizable` behaviours.
"""
@enforce_keys [:stage, :reason]
defstruct [:stage, :reason, __exception__: true]
@behaviour Exception
@type t :: %__MODULE__{
stage: atom(),
reason: any()
}
@doc """
Creates a new `EffectError` from the given stage and reason.
## Examples
iex> Funx.Errors.EffectError.new(:bind, %RuntimeError{message: "boom"})
%Funx.Errors.EffectError{stage: :bind, reason: %RuntimeError{message: "boom"}}
"""
@spec new(atom(), any()) :: t()
def new(stage, reason), do: %__MODULE__{stage: stage, reason: reason}
@impl Exception
def exception(%{stage: stage, reason: reason}) when is_atom(stage),
do: %__MODULE__{stage: stage, reason: reason}
@impl Exception
def message(%__MODULE__{stage: stage, reason: reason}) when is_atom(stage) do
"EffectError at #{stage}: #{Exception.message(reason)}"
rescue
_ -> "EffectError at #{stage}: #{inspect(reason)}"
end
end
defimpl String.Chars, for: Funx.Errors.EffectError do
def to_string(%Funx.Errors.EffectError{stage: stage, reason: reason}) do
"EffectError(#{stage}: #{inspect(reason)})"
end
end
defimpl Funx.Summarizable, for: Funx.Errors.EffectError do
def summarize(%{stage: stage, reason: reason}) do
{:effect_error, [stage: stage, reason: Funx.Summarizable.summarize(reason)]}
end
end