FunConfig Reference

Copy Markdown View Source

FunConfig is the central configuration struct. Each FunConfig maps one {service, request_type} pair to one function call.

Schema

FieldTypeDefaultDescription
request_typeString.t()requiredAPI endpoint name (e.g. "get_user")
serviceatom | String.t()requiredService group name (e.g. "user_service")
nodes[atom] | {m,f,a} | :localrequiredTarget nodes or :local for same-node execution
choose_node_modeatom:randomNode selection strategy (see below)
timeoutinteger | :infinityrequiredExecution timeout in ms (100–300_000 or :infinity)
mfa{module, function, args}requiredThe function to call
arg_typesmap() | nilnilArgument type declarations for validation
arg_orders[String.t()] | :map[]Argument ordering (or :map to pass a map)
response_typeatom:sync:sync | :async | :stream | :none
check_permissionatom | tuplefalsePermission mode (see below)
permission_callback{m,f,a} | nilnilCustom permission check MFA
versionString.t() | nilnilAPI version. "0.0.0" is reserved as a sentinel
disabledbooleanfalseSoft-delete flag
retrynil | number | tuplenilRetry configuration
before_executetuple | nilnilHook called before execution
after_executetuple | nilnilHook called after execution
hook_timeoutpos_integer()5_000Per-hook timeout in ms
request_infobooleanfalseLegacy field, currently unused in execution

Node Selection Strategies (choose_node_mode)

StrategyValueDescription
Random:randomPick a random node
Hash (request_id):hashHash the request_id to pick a node
Hash (arg value){:hash, "user_id"}Hash the value of the named arg
Round-robin:round_robinCycle through nodes in order
Sticky{:sticky, "user_id"}Same key value always maps to the same node (persisted via ETS)

Permission Modes (check_permission)

ModeValueDescription
DisabledfalseNo permission check (default)
Any authenticated:any_authenticatedRequires user_id to be non-nil
Arg-based{:arg, "user_id"}Compares user_id from socket to the named arg value
Role-based{:role, ["admin"]}Checks if any user role is in the allowed list

When permission_callback is set to an MFA tuple, it overrides check_permission entirely.

Response Types (response_type)

TypeDescription
:syncExecute and return the result immediately
:asyncAcknowledge immediately, send result later via {:async_call, result}
:streamStart a StreamCall GenServer that sends chunks via {:stream_response, result}
:noneFire-and-forget; no response sent to the client

Retry Configuration (retry)

ValueDescription
nilNo retry (default)
3Equivalent to {:all_nodes, 3}
{:same_node, 2}Retry on the originally selected node(s)
{:all_nodes, 3}Retry across all available nodes

For nodes: :local, both :same_node and :all_nodes retry locally.

Argument Types (arg_types)

Simple format

arg_types: %{
  "user_id" => :string,
  "age" => :num,
  "active" => :boolean
}

Extended format (with constraints)

arg_types: %{
  "title" => [type: :string, max_bytes: 200],
  "tags" => [type: :list_string, max_items: 10, max_item_bytes: 50],
  "published" => [type: :boolean, default_value: false],
  "metadata" => [type: :map, max_items: 50, required: ["author"], accept: ["author", "email"]]
}

Available types

TypeDescription
:stringUTF-8 binary
:numInteger or float
:booleantrue or false
:uuidUUID string
:datetimeISO 8601 datetime string
:naive_datetimeISO 8601 naive datetime string
:listList of any values
:list_stringList of strings
:list_numList of numbers
:list_uuidList of UUIDs
:mapString-keyed map
:anySkip type checking

Extended format options

OptionApplies toDescription
max_bytes::stringMaximum byte length
max_items:All list/map typesMaximum number of items
max_item_bytes::list_stringMax bytes per list item
allow_nil?:All typesAllow nil values (default: false)
default_value:All typesDefault if arg is missing
required::map onlyList of required map keys
accept::map onlyList of allowed map keys (rejects unknown keys)

Version

The version field is a string (e.g., "1.0.0"). The value "0.0.0" is reserved as a sentinel and cannot be explicitly registered — it is used internally to mean "no version specified". If a config has no version set, it is stored with a nil version key in the cache.

Validation

Use FunConfig.valid?/1 for a quick boolean check or FunConfig.validate_with_details/1 for detailed error messages:

case FunConfig.validate_with_details(config) do
  {:ok, _} -> :valid
  {:error, errors} -> IO.inspect(errors)
end

Validation checks include: request_type is non-empty, service is not nil, nodes is valid, choose_node_mode is recognized, timeout is within bounds, mfa is a valid tuple, arg_types and arg_orders are consistent, response_type is valid, check_permission is valid, retry is valid, hooks are valid MFAs, hook_timeout is positive.

Example

alias PhoenixGenApi.Structs.FunConfig

%FunConfig{
  request_type: "get_user",
  service: "user_service",
  nodes: [:"node1@host", :"node2@host"],
  choose_node_mode: {:sticky, "user_id"},
  timeout: 5_000,
  mfa: {MyApp.Api, :get_user, []},
  arg_types: %{
    "user_id" => :string,
    "fields" => [type: :list_string, max_items: 10]
  },
  arg_orders: ["user_id", "fields"],
  response_type: :sync,
  version: "2.0.0",
  check_permission: {:arg, "user_id"},
  retry: {:all_nodes, 3},
  before_execute: {MyApp.Hooks, :validate_quota},
  after_execute: {MyApp.Hooks, :log_response}
}

What's Next