AshPhoenixGenApi.Domain (ash_phoenix_gen_api v1.0.3)

Copy Markdown View Source

Ash Domain extension for PhoenixGenApi configuration.

This extension provides domain-level configuration for PhoenixGenApi, including default service settings and automatic generation of a "supporter" module that aggregates FunConfigs from all resources in the domain.

The generated supporter module implements the PhoenixGenApi client config interface (get_config/1, get_config_version/1), allowing gateway nodes to pull API configurations from service nodes.

Usage

Add the extension to your Ash domain:

defmodule MyApp.Chat do
  use Ash.Domain,
    extensions: [AshPhoenixGenApi.Domain]

  gen_api do
    service "chat"
    nodes {ClusterHelper, :get_nodes, [:chat]}
    choose_node_mode :random
    timeout 5_000
    response_type :async
    request_info true
    version "0.0.1"

    supporter_module MyApp.Chat.GenApiSupporter
  end

  resources do
    resource MyApp.Chat.DirectMessage
    resource MyApp.Chat.GroupMessage
  end
end

This will generate MyApp.Chat.GenApiSupporter with:

defmodule MyApp.Chat.GenApiSupporter do
  @moduledoc """
  Auto-generated PhoenixGenApi supporter module for MyApp.Chat.
  Aggregates FunConfigs from all resources in the domain.
  """

  alias PhoenixGenApi.Structs.FunConfig

  def get_config(remote_id) do
    {:ok, fun_configs()}
  end

  def get_config_version(remote_id) do
    {:ok, "0.0.1"}
  end

  def fun_configs do
    MyApp.Chat.DirectMessage.__ash_phoenix_gen_api_fun_configs__() ++
      MyApp.Chat.GroupMessage.__ash_phoenix_gen_api_fun_configs__()
  end

  def list_request_types do
    fun_configs() |> Enum.map(& &1.request_type)
  end

  def get_fun_config(request_type) do
    fun_configs() |> Enum.find(&(&1.request_type == request_type))
  end
end

Domain-Level Defaults

Domain-level settings serve as defaults for all resources in the domain that use AshPhoenixGenApi.Resource. Each resource can override these defaults in its own gen_api section.

Resolution order for any setting:

  1. Resource action-level (e.g., action :foo do timeout 10_000 end)
  2. Resource section-level (e.g., gen_api do timeout 5_000 end)
  3. Domain section-level (this extension, e.g., gen_api do timeout 5_000 end)
  4. Built-in defaults (e.g., timeout defaults to 5000)

Gateway Node Configuration

On the Phoenix gateway node, configure the supporter module in config.exs:

config :phoenix_gen_api, :gen_api,
  service_configs: [
    %{
      service: "chat",
      nodes: {ClusterHelper, :get_nodes, [:chat]},
      module: MyApp.Chat.GenApiSupporter,
      function: :get_config,
      args: [:gateway_1]
    }
  ]

Active Push Configuration

In addition to the pull-based model (where the gateway pulls config from service nodes), you can configure the supporter module to actively push its configuration to gateway nodes.

Set push_nodes to specify which gateway nodes to push to:

gen_api do
  service "chat"
  supporter_module MyApp.Chat.GenApiSupporter
  version "0.0.1"
  push_nodes [:"gateway1@host", :"gateway2@host"]
  # Or use an MFA tuple for runtime resolution:
  # push_nodes {ClusterHelper, :get_gateway_nodes, []}
end

This adds the following functions to the generated supporter module:

  • build_push_config/0 - Builds a PushConfig struct from the domain config
  • push_to_gateway/2 - Pushes config to a specific gateway node
  • push_on_startup/2 - Pushes config on application startup
  • verify_on_gateway/2 - Verifies config version on a gateway node
  • resolve_push_nodes/0 - Resolves push_nodes at runtime
  • push_to_configured_nodes/1 - Pushes to all configured push_nodes

Example usage during application startup:

def start(_type, _args) do
  # ... start supervision tree, then:
  MyApp.Chat.GenApiSupporter.push_to_configured_nodes()
  # Or push to a specific node:
  MyApp.Chat.GenApiSupporter.push_on_startup(:"gateway1@host")
end

Summary

Functions

gen_api(body)

(macro)