# `PhoenixGenApi.Executor`
[🔗](https://github.com/ohhi-vn/phoenix_gen_api/blob/main/lib/phoenix_gen_api/executor/executor.ex#L1)

The core execution engine of PhoenixGenApi.

This module is responsible for taking a `Request` struct, looking up its
corresponding `FunConfig`, and executing the function call according to the
configuration. It handles synchronous, asynchronous, and streaming responses.

## Worker Pools

Async and stream calls now use dedicated worker pools instead of spawning
unlimited processes. This provides better resource management and prevents
system overload.

## Error Handling

All execution paths catch errors, exits, and throws, converting them to
safe error responses. Internal error details are only exposed when
`:detail_error` is enabled in configuration.

## Node Fallback

When executing on remote nodes, if the primary node fails, the executor
will attempt to fall back to another available node (if configured).

## Retry

When a request execution fails (returns `{:error, _}` or `{:error, _, _}`),
the executor can retry according to the `retry` field in `FunConfig`.

- **`{:same_node, n}`**: Retries the request on the same node(s) that were
  originally selected by the `choose_node_mode` strategy. Useful when the
  failure might be transient (e.g., temporary network glitch).

- **`{:all_nodes, n}`**: On each retry, fetches the full list of available
  nodes and tries all of them. Useful when a node might be down and you
  want to try other nodes.

- **Local execution**: For `nodes: :local`, both `:same_node` and
  `:all_nodes` retry on the same local machine since there's only one node.

- **Shorthand**: A plain number (e.g., `3`) is equivalent to
  `{:all_nodes, 3}`.

- **`nil`**: No retry (default, backward compatible).

Retry attempts emit telemetry events at `[:phoenix_gen_api, :executor, :retry]`
with measurements `%{attempt: n}` and metadata
`%{mode: :same_node | :all_nodes, type: :local | :remote}`.

# `attach_telemetry`

Attaches a telemetry handler to executor events.

## Events

- `[:phoenix_gen_api, :executor, :request, :start]` - Emitted when request execution starts
- `[:phoenix_gen_api, :executor, :request, :stop]` - Emitted when request execution completes
- `[:phoenix_gen_api, :executor, :request, :exception]` - Emitted when request execution fails

## Examples

    :telemetry.attach(
      "my-executor-handler",
      [:phoenix_gen_api, :executor, :request, :stop],
      fn event, measurements, metadata, config ->
        ...
      end,
      %{}
    )

# `detach_telemetry`

Detaches telemetry handlers by ID.

# `execute!`

```elixir
@spec execute!(PhoenixGenApi.Structs.Request.t()) ::
  PhoenixGenApi.Structs.Response.t()
```

Executes a request.

# `execute_params!`

```elixir
@spec execute_params!(map()) :: PhoenixGenApi.Structs.Response.t()
```

Executes a request from a map of parameters.

This is a convenience function that decodes the params into a `Request` struct
before calling `execute!/1`.

# `execute_with_config!`

# `execute_with_timeout!`

```elixir
@spec execute_with_timeout!(PhoenixGenApi.Structs.Request.t(), non_neg_integer()) ::
  PhoenixGenApi.Structs.Response.t()
```

Executes a request with a custom timeout.

This function wraps `execute!/1` with a timeout to prevent long-running
requests from blocking the caller indefinitely.

## Parameters

  - `request` - The request to execute
  - `timeout` - Timeout in milliseconds (default: 5000)

## Returns

  - `Response.t()` - The execution result or timeout error

# `sync_call`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
