Current section

Files

Jump to
quackdb lib quack_db transport.ex
Raw

lib/quack_db/transport.ex

defmodule QuackDB.Transport do
@moduledoc """
HTTP transport for Quack binary requests.
Sends encoded protocol messages with DuckDB-compatible content negotiation and
normalizes HTTP/client failures into `QuackDB.Error` values.
"""
alias QuackDB.Error
@type option :: {:timeout, timeout()} | {:req_options, Keyword.t()}
@spec post(URI.t(), iodata(), [option]) :: {:ok, binary()} | {:error, Error.t()}
def post(uri, body, options \\ []) do
request_options = [
url: URI.to_string(uri),
body: IO.iodata_to_binary(body),
headers: headers(),
receive_timeout: Keyword.get(options, :timeout, 15_000)
]
options
|> Keyword.get(:req_options, [])
|> Keyword.merge(request_options)
|> Req.post()
|> normalize_response()
end
defp headers do
[
{"content-type", "application/duckdb"},
{"accept", "application/duckdb, application/vnd.duckdb, application/octet-stream"}
]
end
defp normalize_response({:ok, %{status: 200, body: body}}) when is_binary(body) do
{:ok, body}
end
defp normalize_response({:ok, %{status: status, body: body}}) do
message = "Quack server returned HTTP #{status}"
{:error,
Error.new(:http_error, message, source: :transport, metadata: %{body: body, status: status})}
end
defp normalize_response({:error, reason}) do
{:error,
Error.new(:transport_error, Exception.message(reason),
source: :transport,
metadata: %{reason: reason}
)}
end
end