# `GRPC.Client.Connection`
[🔗](https://github.com/elixir-grpc/grpc/tree/master/grpc/blob/v1.0.5/lib/grpc/client/connection.ex#L1)

Connection manager for gRPC client channels, with optional load balancing
and name resolution support.

A `Conn` process manages one or more underlying gRPC connections
(`GRPC.Channel` structs) and exposes a virtual channel to be used by
client stubs. The orchestration process runs as a `GenServer` registered
in a node-local `Registry`, so named channels are scoped to the current
BEAM node.

## Overview

* `connect/2` – establishes a client connection (single or multi-channel).
* `pick/2` – chooses a channel according to the active load-balancing policy.
* `disconnect/1` – gracefully closes a connection and frees resources.

Under the hood:

* The target string is resolved using a [Resolver](GRPC.Client.Resolver).
* Depending on the target and service config, a load-balancing module is chosen
  (e.g. `PickFirst`, `RoundRobin`).
* Each call to `pick/2` dispatches to the LB module, which selects a channel
  per request. DNS re-resolution reconciles the LB's channel list in place.

## Supervised connections

For long-running clients, declare the connection in your own supervision
tree instead of calling `connect/2` at runtime. In that mode, establishment
happens asynchronously after process start: if the backend is unreachable,
the process stays alive and retries with exponential backoff instead of
failing supervisor startup. Use `await_ready/2` to block until the channel
is usable.

    children = [
      {GRPC.Client.Connection,
       name: MyApp.PaymentsConnection,
       target: "dns://payments.internal:50051",
       lb_policy: :round_robin}
    ]

    :ok = GRPC.Client.Connection.await_ready(MyApp.PaymentsConnection, 10_000)
    # use get_channel/1 for the non-raising variant
    channel = GRPC.Client.Connection.get_channel!(MyApp.PaymentsConnection)
    Payments.Stub.charge(channel, request)

The channel handle returned by `get_channel/1` is valid as soon as the
process is running, even while the connection is still being established;
RPCs return `{:error, :no_connection}` style errors until then.

`connect/2` keeps its historical fail-fast contract: it blocks until the
first establishment attempt finishes and returns `{:error, reason}` (tearing
the process down) if that attempt fails.

## Supervisor memory

Connection start arguments (for example large default headers) can linger in
the `GRPC.Client.Supervisor` process heap after children exit. That supervisor
therefore hibernates when idle and runs fullsweep GCs more often. Tune via
config:

    config :grpc, GRPC.Client.Application,
      hibernate_after: 15_000,
      fullsweep_after: 20

* `:hibernate_after` – idle ms before the supervisor hibernates (default: `15_000`)
* `:fullsweep_after` – minor GCs between fullsweeps on the supervisor (default: `20`)

## Target syntax

The `target` argument to `connect/2` accepts URI-like strings that are resolved
via the configured `Resolver` (default `GRPC.Client.Resolver`).

Examples of supported formats:

  * `"dns://example.com:50051"`
  * `"ipv4:10.0.0.5:50051"`
  * `"unix:/tmp/my.sock"`
  * `"xds:///my-service"`
  * `"127.0.0.1:50051"` (implicit DNS / fallback to IPv4)

See [`GRPC.Client.Resolver`](GRPC.Client.Resolver) for the full specification.

## Telemetry

Connection processes emit the following events:

  * `[:grpc, :client, :connection, :connected]` – establishment succeeded,
    including re-establishment after retries or a supervisor restart.
    * Measurements: `:retry_attempt` – failed attempts before this success
    * Metadata: `:name`, `:target`, `:pid`
  * `[:grpc, :client, :connection, :connect_error]` – an establishment
    attempt failed and a retry was scheduled.
    * Measurements: `:retry_delay` – milliseconds until the next attempt
    * Metadata: `:name`, `:target`, `:pid`, `:reason`, `:retry_attempt`
  * `[:grpc, :client, :connection, :disconnected]` – the connection process
    shut down, after its resources were released.
    * Measurements: none
    * Metadata: `:name`, `:target`, `:pid`, `:reason`
  * `[:grpc, :client, :connection, :await_ready, :start]` – a caller started
    waiting in `await_ready/2`.
    * Measurements: `:system_time`
    * Metadata: `:name`, `:target`, `:pid`, `:caller`
  * `[:grpc, :client, :connection, :await_ready, :stop]` – the wait ended.
    * Measurements: `:duration` – as measured through `System.monotonic_time()`
    * Metadata: `:name`, `:target`, `:pid`, `:caller`, `:result` – `:ok`
      when the connection became ready, `:disconnected` when it shut down
      while the caller was waiting, `:abandoned` when the caller died or
      timed out and re-entered the wait

The `:pid` metadata is the connection process, useful for correlating
events with process logs and crash reports.

## Examples

### Basic connect and RPC

    iex> opts = [adapter: GRPC.Client.Adapters.Gun]
    iex> {:ok, ch} = GRPC.Client.Connection.connect("127.0.0.1:50051", opts)
    iex> req = %Grpc.Testing.SimpleRequest{response_size: 42}
    iex> {:ok, resp} = Grpc.Testing.TestService.Stub.unary_call(ch, req)
    iex> resp.response_size
    42

### Using interceptors and custom adapter

    iex> opts = [interceptors: [GRPC.Client.Interceptors.Logger],
    ...>         adapter: GRPC.Client.Adapters.Mint]
    iex> {:ok, ch} = GRPC.Client.Connection.connect("dns://my-service.local:50051", opts)
    iex> {:ok, channel} = GRPC.Client.Connection.pick(ch)
    iex> channel.host
    "127.0.0.1"

### Unix socket target

    iex> {:ok, ch} = GRPC.Client.Connection.connect("unix:/tmp/service.sock")
    iex> Grpc.Testing.TestService.Stub.empty_call(ch, %{})

### Disconnect

    iex> {:ok, ch} = GRPC.Client.Connection.connect("127.0.0.1:50051")
    iex> GRPC.Client.Connection.disconnect(ch)
    {:ok, %GRPC.Channel{...}}

# `await_ready`

Blocks until the connection has at least one established channel.

Returns `:ok` once established, or `{:error, :timeout}` if the connection
is still retrying when `timeout` elapses. Unlike `connect/2`, a failed
establishment attempt does not resolve the wait: the process keeps
retrying with backoff and this call returns as soon as an attempt succeeds.

Returns `{:error, :not_started}` if the connection is not running, or if it
is disconnected or shut down while waiting.

## Examples

Waiting for a supervised connection before issuing the first RPC, for
example inside a release readiness check or a worker's `init/1`:

    case GRPC.Client.Connection.await_ready(MyApp.PaymentsConnection, 10_000) do
      :ok ->
        channel = GRPC.Client.Connection.get_channel!(MyApp.PaymentsConnection)
        Payments.Stub.charge(channel, request)

      {:error, :timeout} ->
        # Still unreachable after 10s; the process keeps retrying in the
        # background, so a later await_ready/2 or RPC may succeed.
        {:error, :payments_unavailable}
    end

It also accepts the channel handle returned by `get_channel/1`:

    {:ok, channel} = GRPC.Client.Connection.get_channel(MyApp.PaymentsConnection)
    :ok = GRPC.Client.Connection.await_ready(channel, 10_000)

# `child_spec`

Returns a child spec for running a connection under a supervisor.

Accepts the same options as `connect/2` plus the required `:target` and
`:name` keys. The spec only captures the target and options, so a restarted
process re-resolves and re-dials from scratch instead of reusing stale
state.

# `connect`

Establishes a new client connection to a gRPC server or set of servers.

The `target` string determines how the endpoints are resolved
(see [Resolver](GRPC.Client.Resolver)).

Options:

  * `:adapter` – transport adapter module (default: `GRPC.Client.Adapters.Gun`)
  * `:adapter_opts` – options passed to the adapter
  * `:resolver` – resolver module (default: `GRPC.Client.Resolver`)
  * `:lb_policy` – load-balancing policy (`:pick_first`, `:round_robin`)
  * `:interceptors` – list of client interceptors
  * `:codec` – request/response codec (default: `GRPC.Codec.Proto`)
  * `:compressor` / `:accepted_compressors` – message compression
  * `:headers` – default metadata headers
  * `:connect_timeout` – how long `connect/2` waits for the first
    establishment attempt in ms (default: 15000)
  * `:resolve_interval` – DNS re-resolution interval in ms (default: 30000)
  * `:max_resolve_interval` – backoff cap in ms (default: 300000)
  * `:min_resolve_interval` – rate-limit floor in ms (default: 5000)

Returns:

  * `{:ok, channel}` – a `GRPC.Channel` usable with stubs
  * `{:error, {:already_started_with_different_target, target}}` – the name
    is already registered to a connection with a different target
  * `{:error, reason}` – if connection fails

## Examples

    iex> {:ok, ch} = GRPC.Client.Connection.connect("127.0.0.1:50051")
    iex> Grpc.Testing.TestService.Stub.empty_call(ch, %{})

# `disconnect`

Disconnects a channel previously returned by `connect/2`.

This will close all underlying real connections for the orchestrator
and stop its process.

Returns `{:ok, channel}` on success.

## Example

    iex> {:ok, ch} = GRPC.Client.Connection.connect("127.0.0.1:50051")
    iex> GRPC.Client.Connection.disconnect(ch)
    {:ok, %GRPC.Channel{}}

# `get_channel`

Returns the `GRPC.Channel` handle for a running named connection.

The handle is a lightweight identity struct: stubs resolve it to a healthy
underlying connection on every RPC, so it stays valid across reconnects and
endpoint changes and can be fetched once and cached. It is readable as soon
as the process is running, even while establishment is still in progress.

Returns `{:error, :not_started}` if no connection with that name is running.

# `get_channel!`

Same as `get_channel/1`, but raises if the connection is not running.

# `pick_channel`

Picks a channel from the orchestrator according to the active
load-balancing policy.

Normally, you don’t need to call `pick/2` directly – client stubs do this
automatically – but it can be useful when debugging or testing.

Returns:

  * `{:ok, channel}` – the chosen `GRPC.Channel`
  * `{:error, :no_connection}` – if the orchestrator is not available

## Example

    iex> {:ok, ch} = GRPC.Client.Connection.connect("dns://my-service.local:50051")
    iex> GRPC.Client.Connection.pick(ch)
    {:ok, %GRPC.Channel{host: "192.168.1.1", port: 50051}}

# `resolve_now`

Triggers an immediate DNS re-resolution, subject to rate limiting.

Intended for use by health checks or heartbeat mechanisms that detect
a backend has gone away and want to force a fresh DNS lookup.

# `start_link`

Starts a connection process linked to the caller.

Accepts the same options as `child_spec/1`. Establishment (resolution and
dialing) happens asynchronously after the process starts; use
`await_ready/2` to block until the channel is usable.

# `start_link`

---

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