# `Infusion.Runtime.Request`
[🔗](https://github.com/mandar1045/infusion/blob/v0.1.0/runtime/lib/infusion/runtime/request.ex#L1)

Sends one API call: builds the HTTP request from an operation, retries it
when that is safe, and decodes the response.

Generated SDKs call `run/5` with an operation described as data:

    %{
      id: "retrieveModel",
      method: :get,
      path: "/models/{model}",
      path_params: ["model"],
      # {option key, name on the wire, location}
      params: [{:limit, "limit", :query}, {:organization, "OpenAI-Organization", :header}],
      body: nil | :json | :form | :multipart,
      response: Infusion.Runtime.Schema type | nil,
      server: nil | "https://other.host"
    }

Parameters are given as a map or keyword list. Known ones go where the
operation says; unknown ones go into the body, or into the query when the
operation has no body, so parameters added to the API after the SDK was
generated can still be sent.

## Retries

Like the official SDKs: up to `max_retries` (2) retries on connection
errors, timeouts, 408, 409, 429 and 5xx. A `x-should-retry` response
header overrides that decision either way. The wait is the server's
`retry-after-ms` or `retry-after` when given (up to a minute), otherwise
`min(0.5s * 2^n, 8s)` minus up to 25% jitter.

## Options of a call

Any `Infusion.Runtime.Config` setting (`timeout`, `max_retries`,
`headers`, `api_key`, ...), plus:

  * `raw: true`: return `{:ok, %Req.Response{}}` with the decoded body,
    for headers and status
  * `idempotency_key: "..."`: use this key instead of a generated one

## Telemetry

`[:infusion, :request, :start | :stop | :exception]`, with `:operation`,
`:method` and `:url` in the metadata; `:stop` adds `:status` (or
`:error`) and `:retries`.

# `run`

```elixir
@spec run(
  Infusion.Runtime.Config.t(),
  map(),
  [term()],
  map() | keyword() | term(),
  keyword()
) ::
  {:ok, term()} | {:error, Infusion.Runtime.Error.t()}
```

Runs `operation` with the positional `path_args`, `params` and call `opts`.

# `stream`

```elixir
@spec stream(
  Infusion.Runtime.Config.t(),
  map(),
  [term()],
  map() | keyword() | term(),
  keyword()
) ::
  {:ok, Enumerable.t()} | {:error, Infusion.Runtime.Error.t()}
```

Runs a streaming operation: `{:ok, stream}` of decoded events, or
`{:error, error}` when the request fails before any event arrives.

The operation says how to ask for a stream (`stream_param: {"stream", true}`)
and how to decode each event (`stream_response`). Until the response
starts, the request is retried like any other; once events flow it never
is. The stream is lazy and must be consumed by the process that called
this; stopping early (`Enum.take/2`) closes the connection. An error the
API sends inside the stream is raised as `Infusion.Runtime.Error`. A
`data: [DONE]` event ends the stream.

# `unwrap!`

Unwraps a result for the `!` functions: returns the value or raises the error.

---

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