Packages
phoenix_gen_api
2.1.1
2.22.0
2.21.1
2.21.0
2.20.1
2.20.0
2.19.0
2.18.1
2.18.0
2.17.1
2.17.0
2.16.0
2.15.0
2.14.0
2.13.0
2.12.0
2.11.0
2.10.0
2.9.1
2.9.0
2.8.0
2.7.0
2.6.1
2.6.0
2.5.0
2.4.0
2.3.0
2.2.0
2.1.1
2.1.0
2.0.1
2.0.0
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
0.2.1
0.2.0
0.1.1
0.1.0
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
A library for fast develop APIs in Elixir cluster, using Phoenix Channels for transport data, auto pull api configs from service nodes.
Current section
Files
Jump to
Current section
Files
lib/phoenix_gen_api/structs/fun_config.ex
defmodule PhoenixGenApi.Structs.FunConfig do
@moduledoc """
Defines the configuration for a function that can be called through the API.
This struct holds all the necessary information to route, validate, and execute
a function call based on an incoming request.
"""
alias PhoenixGenApi.ArgumentHandler
alias PhoenixGenApi.NodeSelector
alias PhoenixGenApi.Permission
alias PhoenixGenApi.Structs.Request
require Logger
@type t :: %__MODULE__{
request_type: String.t(),
service: atom() | String.t(),
nodes: list(atom()) | {module(), function(), args :: list()},
choose_node_mode: atom() | {atom(), atom()},
timeout: integer() | :infinity,
mfa: {module(), function(), args :: list()},
arg_types: map() | nil,
arg_orders: list(String.t()),
response_type: :sync | :async | :stream | :none,
check_permission: false | {:arg, String.t()},
request_info: boolean()
}
defstruct [
:request_type,
:service,
:nodes,
:choose_node_mode,
:timeout,
:mfa,
:arg_types,
:arg_orders,
:response_type,
request_info: false,
check_permission: false
]
@doc """
Selects a target node for the request based on the `choose_node_mode` strategy.
"""
def get_node(config = %__MODULE__{}, request = %Request{}) do
NodeSelector.get_node(config, request)
end
@doc """
Checks if the service is configured to run locally.
"""
def is_local_service?(config = %__MODULE__{}) do
config.nodes == :local
end
@doc """
Validates and converts the request arguments based on the `arg_types` and `arg_orders` configuration.
"""
def convert_args!(config = %__MODULE__{}, request = %Request{}) do
ArgumentHandler.convert_args!(config, request)
end
@doc """
Checks if the request has the necessary permissions to be executed.
"""
def check_permission!(request = %Request{}, config = %__MODULE__{}) do
Permission.check_permission!(request, config)
end
@doc """
Validates the function configuration.
"""
# TO-DO: Add unittest for this function.
def valid?(config = %__MODULE__{}) do
incorrected_keys =
[
# choose_node_mode: NodeSelector.choose_node_valid?(config.choose_node_mode),
response_type: config.response_type in [:sync, :async, :stream, :none],
request_info: config.request_info in [true, false],
service: config.service != nil,
nodes: valid_nodes?(config.nodes),
mfa: valid_mfa?(config.mfa),
args: valid_args?(config.arg_types, config.arg_orders),
check_permission: valid_check_permission?(config.check_permission, config.arg_types)
]
|> Enum.filter(fn {_, valid} -> valid == false end)
|> Enum.map(fn {key, _} -> key end)
if Enum.empty?(incorrected_keys) do
true
else
Logger.error("Invalid configurations: #{inspect(incorrected_keys)} for #{inspect(config)}")
false
end
end
defp valid_nodes?(nodes) do
case nodes do
[] -> false
[_ | _] -> true
{mod, fun, args} when is_atom(mod) and is_atom(fun) and is_list(args) -> true
_ -> false
end
end
defp valid_mfa?({mod, fun, args}) when is_atom(mod) and is_atom(fun) and is_list(args), do: true
defp valid_mfa?(_), do: false
defp valid_check_permission?(false, _), do: true
defp valid_check_permission?({:arg, arg}, args) do
Map.has_key?(args, arg)
end
defp valid_args?(nil, nil), do: true
defp valid_args?(nil, _arg_orders), do: false
defp valid_args?(arg_types, arg_orders) when map_size(arg_types) == 0 do
cond do
arg_orders == [] -> true
arg_orders == nil -> true
true -> false
end
end
defp valid_args?(arg_types, arg_orders) when map_size(arg_types) == 1 do
cond do
arg_orders == [] ->
true
arg_orders == nil ->
true
true ->
MapSet.new(Map.keys(arg_types)) == MapSet.new(arg_orders)
end
end
defp valid_args?(_arg_types, nil), do: false
defp valid_args?(arg_types, arg_orders) when map_size(arg_types) != length(arg_orders),
do: false
defp valid_args?(arg_types, arg_orders) do
args = MapSet.new(Map.keys(arg_types))
orders = MapSet.new(arg_orders)
MapSet.equal?(args, orders)
end
end