Caller-supervised shared-channel cache for Arcadic.Transport.Grpc.
A gRPC channel is HTTP/2-multiplexed — many concurrent streams share ONE connection — so this is a
shared channel cache (one long-lived channel per {host, port, tls?, trust-selection} endpoint
reused across ALL calls with the SAME trust config), NOT an exclusive checkout pool that would
serialize streams. It opt-in: add
children = [{Arcadic.Transport.Grpc.ChannelPool, []}]to your supervision tree. When it is running, the transport reuses its channel; when it is absent,
the transport falls back to a fresh per-call connect (no behavior change). Tenant-blind — keyed on
the endpoint + trust selection only, carrying no database/scope. Rationale for the process: a live
gRPC channel is a socket/connection process (adapter_payload.conn_pid), not an immutable value
copied into a pure-data Conn — sharing one requires a process, which is why the pool is opt-in
and caller-supervised rather than transport-internal.
The CONNECT itself runs in the CALLER's process, never inside the GenServer: a connect can block for the adapter's full connect timeout (grpc 1.x default 15s, ×2 with the transport's transient retry), and serializing that inside the pool would queue every OTHER endpoint's checkout behind one dead endpoint. The GenServer only makes two O(1) decisions — a cache lookup, and a first-wins register when two concurrent first-connects race (the loser's channel serves its own call and is then best-effort disconnected). A dead channel (its adapter connection process gone) is transparently replaced on the next checkout.
Summary
Functions
Return a healthy channel for key, connecting via connect_fn (a 0-arity -> {:ok, channel} | {:error, term}) and caching it if the endpoint has no live channel yet. The connect runs in the
CALLER process; concurrent first-connects race and the first registered channel wins.
Returns a specification to start this module under a supervisor.
Functions
Return a healthy channel for key, connecting via connect_fn (a 0-arity -> {:ok, channel} | {:error, term}) and caching it if the endpoint has no live channel yet. The connect runs in the
CALLER process; concurrent first-connects race and the first registered channel wins.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec start_link(keyword()) :: GenServer.on_start()