TypeDB.Config (TypeDB v0.7.0)

Copy Markdown View Source

Validated connection configuration.

You normally never build this yourself — pass the options below to TypeDB.start_link/1 and they are validated into a %TypeDB.Config{}.

Options

  • :url — server URL, e.g. "http://localhost:8000". A bare "host:port" or "host" is accepted and defaults to http. Defaults to "http://localhost:8000".

  • :username / :password — credentials used against POST /v1/signin. Required unless :token is given.

  • :token — a pre-issued bearer token, used instead of signing in. When the token expires it cannot be renewed, so prefer credentials for long-lived connections.

  • :name — registered name of the connection process. Defaults to TypeDB.

  • :timeout — per-request receive timeout in ms. Defaults to 60_000.

  • :connect_timeout — TCP/TLS connect timeout in ms. Defaults to 10_000.

  • :http{adapter_module, adapter_opts}. Defaults to {TypeDB.HTTP.Finch, []}. See TypeDB.HTTP for the alternatives and why this is the default.

  • :max_retries — how many times to retry a request that is safe to re-send, after a transport failure, a timeout or a status in :retry_on_status. Defaults to 1.

    Safety is decided per operation, not per HTTP method: reads, analyze, rollback, close, Database.create/2 and User.set_password/3 are retried; writes, schema changes, commit and User.create/3 are not.

  • :max_auth_renewals — how many times a single request will renew its token and retry after a 401. Defaults to 2; more than one matters only when a burst of requests is wide enough for the freshly minted token to expire before every one of them has used it.

  • :answer_count_limit — how many answers a query may materialise, applied unless the query passes its own. Unset by default, which means TypeDB's own default of 10,000 answers per read applies: a bigger match comes back truncated with a warning attached rather than failing. Set this to raise that ceiling for every query on the connection, or to lower it — the HTTP API is not streaming, so an unbounded match is materialised whole at both ends.

  • :retry_backoff — either {:exponential, base_ms} or a (attempt -> ms) function. Defaults to {:exponential, 100}. The {:exponential, _} form is jittered: the delay before retry n is drawn uniformly from 0..base_ms * 2 ** (n - 1), so that callers who failed together do not retry together. Pass a function when you need a delay you can predict.

  • :retry_max_delay — the ceiling on any single backoff, in ms, whichever form produced it. Defaults to 5_000; :infinity opts out. Exponential growth is otherwise unbounded, and the sleep happens in the calling process — with max_retries: 10 and the default base, the last wait would be over fifty seconds.

  • :retry_on_status — response statuses to treat as retryable, in addition to transport failures and timeouts. Defaults to [429, 502, 503, 504]; [] opts out. These are what a proxy, an ingress or a load balancer answers while TypeDB restarts, and what the server answers when it is shedding load — the failures retrying exists for. A retry-after header is honoured when it carries a number of seconds, still bounded by :retry_max_delay. The same idempotence rule applies as to any other retry, so a write is never re-sent.

  • :log_level — the quietest level this connection will log at, one of :debug, :info, :warning, :error or :none. Defaults to :debug, which logs everything the driver has to say; :none silences it. A library that cannot be turned down gets turned off, and filtering the global Logger by module is a blunt instrument when an application has several connections. See the "Logging" section of TypeDB for every line the driver can emit.

  • :deadline — a wall-clock budget in ms for a whole call, across every retry and every wait between them. Defaults to :infinity.

    :timeout bounds one attempt; this bounds the operation. Without it a caller who asks for timeout: 5_000 can still block for 5_000 * (max_retries + 1) plus the backoffs, because each retry gets the full timeout again. Each attempt is given whichever is smaller, its own timeout or the budget that is left, and a retry that could not finish inside the budget is not started.

    It cannot cut short a connect that is already blocking. The budget is enforced between attempts and by shortening each attempt's :timeout, which is the receive timeout; opening the socket is bounded by :connect_timeout alone. So a call to a host that accepts nothing — a black-holed address, a dropped route — can outlive its :deadline by up to one :connect_timeout. Size the two together. Making this exact would mean deriving the connect timeout per request, which TypeDB.HTTP.Finch cannot do: Mint reads it from the pool, and the pool is built once.

Reading configuration from the environment

TypeDB.start_link(
  url: System.fetch_env!("TYPEDB_URL"),
  username: System.fetch_env!("TYPEDB_USERNAME"),
  password: System.fetch_env!("TYPEDB_PASSWORD")
)

Summary

Functions

The HTTP API version this driver speaks.

Computes the backoff delay, in milliseconds, before retry attempt (1-based).

The option keys new/1 accepts. Anything else is rejected.

Validates connection options.

Same as new/1 but raises TypeDB.Error on invalid options.

Builds the absolute URL for an unversioned API path, such as /health.

Builds the absolute URL for a versioned API path.

Types

t()

@type t() :: %TypeDB.Config{
  answer_count_limit: pos_integer() | nil,
  base_url: String.t(),
  connect_timeout: timeout(),
  deadline: timeout(),
  http_adapter: module(),
  http_opts: keyword(),
  log_level: atom(),
  max_auth_renewals: non_neg_integer(),
  max_retries: non_neg_integer(),
  name: atom(),
  password: String.t() | nil,
  retry_backoff:
    {:exponential, pos_integer()} | (pos_integer() -> non_neg_integer()),
  retry_max_delay: timeout(),
  retry_on_status: [pos_integer()],
  static_token: String.t() | nil,
  timeout: timeout(),
  username: String.t() | nil
}

Functions

api_version()

@spec api_version() :: String.t()

The HTTP API version this driver speaks.

backoff(config, attempt)

@spec backoff(t(), pos_integer()) :: non_neg_integer()

Computes the backoff delay, in milliseconds, before retry attempt (1-based).

{:exponential, base} is jittered: the delay is drawn uniformly from 0..base * 2 ** (attempt - 1). A function is used as it returns. Either way the result is capped by :retry_max_delay.

known_options()

@spec known_options() :: [atom()]

The option keys new/1 accepts. Anything else is rejected.

new(opts)

@spec new(keyword()) :: {:ok, t()} | {:error, TypeDB.Error.t()}

Validates connection options.

Returns {:ok, config} or {:error, %TypeDB.Error{kind: :config}}.

new!(opts)

@spec new!(keyword()) :: t()

Same as new/1 but raises TypeDB.Error on invalid options.

raw_url(config, path)

@spec raw_url(t(), String.t()) :: String.t()

Builds the absolute URL for an unversioned API path, such as /health.

url(config, path)

@spec url(t(), String.t()) :: String.t()

Builds the absolute URL for a versioned API path.

iex> config = TypeDB.Config.new!(url: "http://localhost:8000", token: "t")
iex> TypeDB.Config.url(config, "/databases/social")
"http://localhost:8000/v1/databases/social"