Ankusa.Config (ankusa v0.7.0)

Copy Markdown View Source

The configuration struct passed down the supervision tree at start. No Application.get_env/2 buried in call sites — instance-scoped config falls out of this for free.

Summary

Functions

The address a listener binds: a strict IPv4/IPv6 literal string, or an :inet address tuple.

Build a %Ankusa.Config{} from a keyword list, deep-merging the map-valued sections (:listener, :batcher, :dispatch, :storage, :claim_check, :backup, :admin, :metrics, :routes, :rate_limits, :dedupe, :fleet, :quarantine, :tenants, :lifecycle, :egress, :secrets) over the defaults (egress.pools is merged one level down). Every tls block (listener.tls, admin.tls, routes.admin.tls, claim_check.tls, metrics.tls) is validated and normalised by Ankusa.Listener.normalize_tls!/2, and listener.num_acceptors: nil becomes two per scheduler.

Parse a comma-separated ANKUSA_ROLES-shaped string into role atoms. Never calls String.to_atom/1 — each part must name one of the fixed roles (edge, dispatch, storage, claim_check).

Absolute path for an instance-scoped data sub-directory.

Is a role enabled for this node?

Types

t()

@type t() :: %Ankusa.Config{
  admin: term(),
  archive: term(),
  audit: term(),
  backup: term(),
  batcher: term(),
  claim_check: term(),
  data_dir: term(),
  dedupe: term(),
  direct_publish_timeout_ms: term(),
  dispatch: term(),
  egress: term(),
  fleet: term(),
  instance: term(),
  intake: term(),
  lifecycle: %{sinks: [{module(), keyword()}]},
  listener: term(),
  max_body_bytes: term(),
  metrics: term(),
  port: term(),
  quarantine: term(),
  queue: term(),
  rate_limits: term(),
  roles: term(),
  route_resolver: term(),
  routes: term(),
  secrets: term(),
  source_store: term(),
  storage: term(),
  store_headers: term(),
  tenants: term(),
  wal: term()
}

Functions

listen_ip!(ip, key)

@spec listen_ip!(term(), String.t()) :: :inet.ip_address()

The address a listener binds: a strict IPv4/IPv6 literal string, or an :inet address tuple.

new(opts \\ [])

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

Build a %Ankusa.Config{} from a keyword list, deep-merging the map-valued sections (:listener, :batcher, :dispatch, :storage, :claim_check, :backup, :admin, :metrics, :routes, :rate_limits, :dedupe, :fleet, :quarantine, :tenants, :lifecycle, :egress, :secrets) over the defaults (egress.pools is merged one level down). Every tls block (listener.tls, admin.tls, routes.admin.tls, claim_check.tls, metrics.tls) is validated and normalised by Ankusa.Listener.normalize_tls!/2, and listener.num_acceptors: nil becomes two per scheduler.

:routes is nested one level deeper than the rest (:routes has its own :cache, :ip_rules, and :admin sections), so put_routes/2 merges those too — routes.cache.max_size keeps the other cache keys.

wal: :none is normalized last: the roles are settled before normalize_wal/1 drops the queue's readers (:dispatch, :storage) from them.

parse_roles!(value)

@spec parse_roles!(String.t()) :: [atom()]

Parse a comma-separated ANKUSA_ROLES-shaped string into role atoms. Never calls String.to_atom/1 — each part must name one of the fixed roles (edge, dispatch, storage, claim_check).

path(config, sub)

@spec path(t(), Path.t()) :: Path.t()

Absolute path for an instance-scoped data sub-directory.

role?(config, role)

@spec role?(t(), atom()) :: boolean()

Is a role enabled for this node?