ExAthena.Error (ExAthena v0.20.0)

Copy Markdown View Source

Canonical error surface across providers.

Summary

Functions

Classify an HTTP status code into an error kind.

Build a canonical error.

Extract a Retry-After hint (in milliseconds) from HTTP response headers.

Delay (ms) to honor before retrying a transient provider error.

Types

kind()

@type kind() ::
  :unauthorized
  | :not_found
  | :rate_limited
  | :timeout
  | :context_length_exceeded
  | :bad_request
  | :server_error
  | :transport
  | :capability
  | :unknown

t()

@type t() :: %ExAthena.Error{
  kind: kind(),
  message: String.t(),
  provider: atom() | module() | nil,
  raw: term() | nil,
  retry_after_ms: non_neg_integer() | nil,
  status: integer() | nil
}

Functions

from_status(status)

@spec from_status(integer()) :: kind()

Classify an HTTP status code into an error kind.

Used by providers that share the OpenAI-style response shape.

new(kind, message, opts \\ [])

@spec new(kind(), String.t(), keyword()) :: t()

Build a canonical error.

retry_after_from_headers(headers)

@spec retry_after_from_headers(term()) :: non_neg_integer() | nil

Extract a Retry-After hint (in milliseconds) from HTTP response headers.

Accepts Req-style header maps (%{"retry-after" => ["30"]}) or tuple lists ([{"Retry-After", "30"}]), matching the header name case-insensitively. Both RFC 9110 value forms are supported:

  • delta-seconds — "30"30_000
  • HTTP-date (IMF-fixdate) — "Sun, 06 Nov 1994 08:49:37 GMT" → the delay from now, clamped to 0 for dates in the past

Returns nil when the header is absent or unparseable.

retry_delay_ms(error, opts \\ [])

@spec retry_delay_ms(
  term(),
  keyword()
) :: non_neg_integer()

Delay (ms) to honor before retrying a transient provider error.

Uses the server's retry_after_ms hint when the error carries one, bounded by :cap (default 30000ms) so a hostile or huge Retry-After header can't stall a run. Falls back to :default (2000ms) when the hint is absent or the term isn't an ExAthena.Error.