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

A GenServer-based cache for storing `FunConfig` structs, using an ETS table as the
backing store.

This cache provides fast, in-memory access to function configurations, which are
used by the `Executor` to handle incoming requests.

The cache is populated and updated by the `ConfigPuller` module, which fetches
configurations from remote nodes.

## Multi-Version Support

Configurations can have multiple versions identified by the `version` field.
The ETS key is `{service, request_type, version}` to support multiple versions
of the same function. When retrieving configs, you can specify a version or
get the latest version.

## Fault Tolerance

- ETS table is automatically cleaned up on process termination
- Invalid configurations are rejected before insertion
- Atomic operations prevent race conditions
- Read concurrency is enabled for high-throughput scenarios

## Security

- Configurations are validated before being added to the cache
- Service names and request types are sanitized
- Only valid `FunConfig` structs are accepted

# `add`

```elixir
@spec add(PhoenixGenApi.Structs.FunConfig.t()) :: :ok | {:error, :invalid_config}
```

Adds a new function configuration to the cache.

Validation is performed on the calling process. The ETS write is then done
directly (safe because the table has `write_concurrency: true`) without
routing through the GenServer mailbox, keeping throughput high under load.

## Returns

  - `:ok` - Configuration was added successfully
  - `{:error, :invalid_config}` - Configuration failed validation

# `batch_add`

```elixir
@spec batch_add([PhoenixGenApi.Structs.FunConfig.t()]) ::
  {:ok, non_neg_integer()} | {:error, :all_invalid}
```

Adds multiple function configurations to the cache in a single ETS call.

Each config is validated on the calling process. All valid configs are then
inserted atomically in one `:ets.insert/2` call, which is significantly faster
than calling `add/1` in a loop (avoids N GenServer round-trips and N ETS calls).

Invalid configs are logged and skipped; they do not abort the batch.

## Returns

  - `{:ok, count}` - Number of configs successfully inserted
  - `{:error, :all_invalid}` - Every config in the batch failed validation

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `clear`

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

Clears all configurations from the cache.

## Returns

  - `:ok` - Cache was cleared successfully

# `count`

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

Returns the total number of configurations in the cache.

## Returns

  The count of cached configurations.

# `delete`

```elixir
@spec delete(String.t() | atom(), String.t(), String.t()) :: :ok
```

Deletes a function configuration from the cache.

## Parameters

  - `service` - The service name (string or atom)
  - `request_type` - The request type (string)
  - `version` - The version to delete (string, defaults to "0.0.0")

## Returns

  - `:ok` - Configuration was deleted (or didn't exist)

# `disable`

```elixir
@spec disable(String.t() | atom(), String.t(), String.t()) ::
  :ok | {:error, :not_found}
```

Disables a function configuration by marking it as disabled.
Disabled configurations will not be returned by `get/3` or executed.

## Parameters

  - `service` - The service name (string or atom)
  - `request_type` - The request type (string)
  - `version` - The version to disable (string, defaults to "0.0.0")

## Returns

  - `:ok` - Configuration was disabled successfully
  - `{:error, :not_found}` - Configuration does not exist

# `enable`

```elixir
@spec enable(String.t() | atom(), String.t(), String.t()) ::
  :ok | {:error, :not_found}
```

Enables a previously disabled function configuration.

## Parameters

  - `service` - The service name (string or atom)
  - `request_type` - The request type (string)
  - `version` - The version to enable (string, defaults to "0.0.0")

## Returns

  - `:ok` - Configuration was enabled successfully
  - `{:error, :not_found}` - Configuration does not exist

# `get`

```elixir
@spec get(String.t() | atom(), String.t(), String.t()) ::
  {:ok, PhoenixGenApi.Structs.FunConfig.t()}
  | {:error, :not_found}
  | {:error, :disabled}
```

Retrieves a function configuration from the cache.

This operation is atomic and uses ETS read concurrency for optimal performance.

## Parameters

  - `service` - The service name (string or atom)
  - `request_type` - The request type (string)
  - `version` - The version to retrieve (string, defaults to "0.0.0")

## Returns

  - `{:ok, config}` - Configuration was found and is enabled
  - `{:error, :not_found}` - Configuration does not exist
  - `{:error, :disabled}` - Configuration exists but is disabled

# `get_all_functions`

```elixir
@spec get_all_functions() :: %{
  required(String.t() | atom()) =&gt; %{required(String.t()) =&gt; [String.t()]}
}
```

Returns a map of all services and their request types in the cache.

## Returns

  A map where keys are service names and values are maps of request types to lists of versions.

# `get_all_services`

```elixir
@spec get_all_services() :: [String.t() | atom()]
```

Returns a list of all service names in the cache.

## Returns

  A list of unique service names.

# `get_functions_from_services`

```elixir
@spec get_functions_from_services([String.t()] | String.t()) :: %{
  required(String.t() | atom()) =&gt; %{required(String.t()) =&gt; [String.t()]}
}
```

Returns a map of all functions from services and their request types in the cache.

## Returns

  A map where keys are service names and values are maps of request types to lists of versions.

# `get_latest`

```elixir
@spec get_latest(String.t() | atom(), String.t()) ::
  {:ok, PhoenixGenApi.Structs.FunConfig.t()} | {:error, :not_found}
```

Retrieves the latest version of a function configuration from the cache.

This operation is atomic and uses ETS read concurrency for optimal performance.

## Parameters

  - `service` - The service name (string or atom)
  - `request_type` - The request type (string)

## Returns

  - `{:ok, config}` - Latest enabled configuration was found
  - `{:error, :not_found}` - No configuration exists

# `start_link`

Starts the `ConfigDb` GenServer.

## Options

  - `:ets_options` - Additional options for the ETS table (default: `[]`)

# `update`

```elixir
@spec update(PhoenixGenApi.Structs.FunConfig.t()) :: :ok | {:error, :invalid_config}
```

Updates an existing function configuration in the cache.
If the configuration does not exist, it will be added.

Validation is performed on the calling process. The ETS write is then done
directly (safe because the table has `write_concurrency: true`) without
routing through the GenServer mailbox.

## Returns

  - `:ok` - Configuration was updated successfully
  - `{:error, :invalid_config}` - Configuration failed validation

---

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