# `Milvex.Retry`

RPC-level retry logic for transient gRPC errors.

Wraps gRPC calls with exponential backoff, retrying on transient failures
like stream closures (INTERNAL) and server unavailability (UNAVAILABLE).

## Retryable gRPC status codes

Only the following transient gRPC status codes are retried:

| Code | Name              | Reason |
|------|-------------------|--------|
| 1    | CANCELLED         | Request cancelled, safe to retry |
| 2    | UNKNOWN           | Unknown server error, may be transient |
| 10   | ABORTED           | Operation aborted, typically retriable |
| 13   | INTERNAL          | Server-side error (e.g., stream closures) |
| 14   | UNAVAILABLE       | Server temporarily unavailable |

## Configuration

Retry behavior is configured via `Milvex.Config`:

- `:retry_max_attempts` - Maximum number of retry attempts (default: 5)
- `:retry_base_delay` - Initial backoff delay in ms (default: 100)
- `:retry_max_delay` - Maximum backoff delay in ms (default: 3000)
- `:retry_timeout` - Total retry time budget in ms (default: 15000)

Per-call overrides can be passed through `RPC.call/5` opts.

# `retry_opts`

```elixir
@type retry_opts() :: [
  retry_max_attempts: non_neg_integer(),
  retry_base_delay: pos_integer(),
  retry_max_delay: pos_integer(),
  retry_timeout: pos_integer()
]
```

# `retryable?`

```elixir
@spec retryable?(term()) :: boolean()
```

Returns whether an error is retryable.

# `with_retry`

```elixir
@spec with_retry(
  (-&gt; {:ok, term()} | {:error, term()}),
  retry_opts(),
  map() | nil
) :: {:ok, term()} | {:error, term()}
```

Executes a function with retry logic for transient errors.

The function is called immediately. If it returns `{:error, error}` and
the error is retryable, it sleeps with exponential backoff and retries.

Retries stop when any of these conditions are met:
- The function returns `{:ok, _}`
- The error is non-retryable
- Max attempts exceeded
- Total timeout exceeded

When `telemetry_metadata` is provided and retries occur, emits a
`[:milvex, :rpc, :retry]` telemetry event with `%{attempts: n}` measurements.

## Options

- `:retry_max_attempts` - Max retries (default: 5)
- `:retry_base_delay` - Initial delay in ms (default: 100)
- `:retry_max_delay` - Max delay in ms (default: 3000)
- `:retry_timeout` - Total time budget in ms (default: 15000)

---

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