# `TruelayerClient.Retry`
[🔗](https://github.com/iamkanishka/truelayer_client/blob/v1.0.0/lib/truelayer_client/retry.ex#L1)

Exponential backoff with cryptographically random full jitter.

## Retry safety

Only idempotent calls are retried unconditionally. POST requests are retried
only when the response carries `Tl-Should-Retry: true` (captured in
`TruelayerClient.Error.retryable?/1`).

Jitter uses `:crypto.strong_rand_bytes/1` — never `rand` — to prevent
thundering-herd reconnections.

# `policy`

```elixir
@type policy() :: %{
  max_attempts: pos_integer(),
  base_delay_ms: non_neg_integer(),
  max_delay_ms: non_neg_integer(),
  multiplier: float()
}
```

# `from_config`

```elixir
@spec from_config(TruelayerClient.Config.t()) :: policy()
```

Build a retry policy from a `TruelayerClient.Config`.

# `run`

```elixir
@spec run(policy(), (-&gt; {:ok, term()} | {:error, TruelayerClient.Error.t()})) ::
  {:ok, term()} | {:error, TruelayerClient.Error.t()}
```

Execute `fun` up to `policy.max_attempts` times, backing off between failures.

`fun` must return `{:ok, result}` or `{:error, %TruelayerClient.Error{}}`.
Retries occur only when `TruelayerClient.Error.retryable?/1` returns `true`.

## Example

    Retry.run(policy, fn ->
      HTTP.json_request(http, config, method: :get, url: url, headers: headers)
    end)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
