-module(livery_client_adapter).
-moduledoc """
Behaviour for an outbound HTTP transport, the client-side dual of
`livery_adapter`.
An adapter owns the wire: it takes a `livery_client:request()` and
produces a `livery_client:response()` (or an error). The composable
layers (timeout, retry, concurrency, circuit breaker) sit above it and
do not care which transport runs underneath. The default adapter is
`livery_client_hackney` (HTTP/1.1, HTTP/2, and HTTP/3 via hackney);
write your own to front a different client.
## Callbacks
- `request(Request, Opts) -> {ok, Response} | {error, term()}` - send
one request. The adapter owns its connections and pooling.
- `read(Reader, Timeout) -> {ok, Data, Reader} | {done, Reader} |
{error, term()}` - *optional*; pull the next chunk of a streamed
response body. Only adapters that return a `{stream, Reader}` response
body implement it.
- `stream(Request, Opts, StreamOpts) -> {ok, Ref} | {error, term()}` -
*optional*; drive the request in a background process owned by the
adapter and deliver the response to `StreamOpts`'s `stream_to` pid as
ordered `{livery_response, Ref, _}` messages (`{status, Status,
Headers}`, `{chunk, Binary}`, `done`, `{error, Reason}`). `StreamOpts`
carries `stream_to` (the recipient) and `flow` (`auto` to push as fast
as the wire allows, `manual` to send one chunk per `stream_next/1`).
`Ref` is opaque and identifies the stream for `stream_next/1` and
`stop_stream/1`.
- `stream_next(Ref) -> ok | {error, term()}` - *optional*; under `flow =>
manual`, ask for one more body chunk.
- `stop_stream(Ref) -> ok` - *optional*; cancel a push stream and release
its connection.
""".
-type stream_ref() :: term().
-type stream_opts() :: #{stream_to := pid(), flow := auto | manual}.
-export_type([stream_ref/0, stream_opts/0]).
-callback request(livery_client:request(), map()) ->
{ok, livery_client:response()} | {error, term()}.
-callback read(term(), timeout()) ->
{ok, binary(), term()} | {done, term()} | {error, term()}.
-callback stream(livery_client:request(), map(), stream_opts()) ->
{ok, stream_ref()} | {error, term()}.
-callback stream_next(stream_ref()) -> ok | {error, term()}.
-callback stop_stream(stream_ref()) -> ok.
-optional_callbacks([read/2, stream/3, stream_next/1, stop_stream/1]).