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

Tracks FunConfig entries that failed validation during pull or push.

Stores the original config (as a map), the reason(s) for failure, the source
(pull or push), the node that provided the config, and a timestamp. Entries
auto-expire after 24 hours (TTL).

## ETS table

- Named `:phoenix_gen_api_config_failed`
- `{:set, :public, read_concurrency: true, write_concurrency: true}`
- Key: `{id}` where `id` is a monotonically increasing integer
- Each entry is a map with `:id`, `:service`, `:request_type`, `:version`,
  `:source`, `:node`, `:reason`, `:config`, `:inserted_at_ms`, `:expires_at_ms`

## TTL

Entries expire after 24 hours. Call `cleanup/0` periodically to purge expired
entries. Query functions (`list/1`, `count/0`) automatically filter out expired
entries.

# `cleanup`

```elixir
@spec cleanup() :: non_neg_integer()
```

Removes all expired entries from the table.
Returns the number of entries removed.

# `clear`

```elixir
@spec clear() :: :ok
```

Clears all entries regardless of expiry.

# `count`

```elixir
@spec count() :: non_neg_integer()
```

Returns the count of non-expired failed entries.

# `init`

```elixir
@spec init() :: :ok
```

Initializes the ETS table. Called by the application supervisor.

# `list`

```elixir
@spec list(keyword()) :: [map()]
```

Returns all non-expired failed entries, optionally filtered by source.

## Options

  * `:source` — filter by `:pull` or `:push`
  * `:service` — filter by service name
  * `:limit` — max number of entries to return (default: 100)
  * `:order` — `:newest_first` (default) or `:oldest_first`

# `record`

```elixir
@spec record(
  map() | PhoenixGenApi.Structs.FunConfig.t(),
  String.t() | [String.t()],
  atom(),
  atom() | nil
) :: map()
```

Records a failed FunConfig validation.

## Parameters

  * `config` — the `%FunConfig{}` struct (or map) that failed
  * `reason` — a string or list of strings describing why it failed
  * `source` — `:pull` or `:push`
  * `node` — the node that provided the config (or `:local` / `nil`)

## Returns

The inserted entry map.

# `start_link`

```elixir
@spec start_link(keyword()) :: {:ok, pid()}
```

Starts the ConfigFailed table under the supervisor.

# `summary`

```elixir
@spec summary() :: map()
```

Returns a summary of failed entries grouped by source.

---

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