Skip to main content

lib/bloccs/effect_error.ex

defmodule Bloccs.EffectError do
  @moduledoc """
  A structured terminal failure, delivered to a `Bloccs.call/4` / `cast/4` caller
  as the `{:error, t()}` result when a request fails before it can reply.

  Without this, a failed request would surface only as a `call/4` timeout — the
  caller could not tell "failed" from "slow". The struct names *where* on the
  request's path the failure occurred:

  - `:validate` — the payload failed a node's inbound `Name@N` schema.
  - `:execute`  — the node's `pure_core` / `effect_shell` raised, returned
    `{:error, _}`, or exceeded its `timeout_ms`.
  - `:dispatch` — the node produced a result but delivering it downstream failed.

  `reason` is the underlying failure term (an exception struct, a schema-error
  tuple, `:timeout`, a `{:dispatch_failed, _}` tuple, …). `attempt` is the retry
  attempt the failure occurred on (`0` for the first).

  Only terminal failures of a node on the request's 1:1 trace are reported — a
  failure that is retried is not (a later attempt may still succeed and reply).
  Correlation does not survive a `[batch]`/`[join]` (which mint a fresh
  `trace_id`); see `Bloccs.Collector`.
  """

  @type phase :: :validate | :execute | :dispatch

  @type t :: %__MODULE__{
          network: atom(),
          node: atom(),
          phase: phase(),
          attempt: non_neg_integer(),
          reason: term()
        }

  @enforce_keys [:network, :node, :phase, :attempt, :reason]
  defstruct [:network, :node, :phase, :attempt, :reason]
end