Foundation.Infrastructure (foundation v0.1.4)

Unified infrastructure facade orchestrating multiple protection patterns.

This module provides a single entry point for coordinating circuit breakers, rate limiting, and connection pooling to create resilient service operations. It implements the Facade pattern to simplify interaction with complex infrastructure components.

Usage

# Execute a protected operation with all safeguards
result = Infrastructure.execute_protected(:external_api, [
  circuit_breaker: :api_breaker,
  rate_limiter: {:api_calls, "user:123"},
  connection_pool: :http_pool
], fn ->
  # Your operation here
  HTTPClient.get("/api/data")
end)

# Configure protection rules
Infrastructure.configure_protection(:external_api, %{
  circuit_breaker: %{
    failure_threshold: 5,
    recovery_time: 30_000
  },
  rate_limiter: %{
    scale: 60_000,    # 1 minute
    limit: 100        # 100 requests per minute
  },
  connection_pool: %{
    size: 10,
    max_overflow: 5
  }
})

Protection Layers

  1. Rate Limiting - First line of defense, prevents overwhelming downstream
  2. Circuit Breaker - Fails fast when downstream is unhealthy
  3. Connection Pool - Manages resource allocation efficiently

Telemetry Events

  • [:foundation, :foundation, :infrastructure, :execute_start]
  • [:foundation, :foundation, :infrastructure, :execute_stop]
  • [:foundation, :foundation, :infrastructure, :execute_exception]
  • [:foundation, :foundation, :infrastructure, :protection_triggered]

Summary

Functions

Configures protection rules for a specific key.

Executes a function with comprehensive protection patterns applied.

Get the status of all infrastructure components.

Gets the current protection configuration for a key.

Gets comprehensive status of all protection layers for a key.

Initialize all infrastructure components.

Initialize a circuit breaker with default configuration.

Initialize a circuit breaker with the given configuration.

Lists all configured protection keys.

Types

execution_result()

@type execution_result() :: {:ok, term()} | {:error, term()}

protection_config()

@type protection_config() :: %{
  circuit_breaker: map(),
  rate_limiter: map(),
  connection_pool: map()
}

protection_key()

@type protection_key() :: atom()

protection_options()

@type protection_options() :: [
  circuit_breaker: atom(),
  rate_limiter: {atom(), binary()},
  connection_pool: atom(),
  timeout: timeout()
]

Functions

configure_protection(protection_key, config)

@spec configure_protection(protection_key(), protection_config()) ::
  :ok | {:error, term()}

Configures protection rules for a specific key.

Stores configuration in internal state for runtime access and validation.

Parameters

  • protection_key - Identifier for protection configuration
  • config - Protection layer configurations

Returns

  • :ok - Configuration stored successfully
  • {:error, reason} - Configuration invalid or storage failed

execute_protected(protection_key, options, fun)

@spec execute_protected(protection_key(), protection_options(), (-> term())) ::
  execution_result()

Executes a function with comprehensive protection patterns applied.

Applies protection layers in order: rate limiting → circuit breaker → connection pooling. Each layer can abort the execution early if protection rules are triggered.

Parameters

  • protection_key - Identifier for protection configuration
  • options - Protection layer options
  • fun - Function to execute with protection

Returns

  • {:ok, result} - Function executed successfully
  • {:error, reason} - Execution blocked or failed

get_infrastructure_status()

@spec get_infrastructure_status() :: {:ok, map()} | {:error, term()}

Get the status of all infrastructure components.

Examples

iex> Infrastructure.get_infrastructure_status()
{:ok, %{fuse: :running, hammer: :running}}

get_protection_config(protection_key)

@spec get_protection_config(protection_key()) :: {:ok, any()} | {:error, any()}

Gets the current protection configuration for a key.

Parameters

  • protection_key - Identifier for protection configuration

Returns

  • {:ok, config} - Current configuration
  • {:error, :not_found} - No configuration exists

get_protection_status(protection_key)

@spec get_protection_status(protection_key()) :: {:ok, map()} | {:error, term()}

Gets comprehensive status of all protection layers for a key.

Parameters

  • protection_key - Identifier for protection status

Returns

  • {:ok, status} - Status of all protection layers
  • {:error, reason} - Status retrieval failed

initialize_all_infra_components()

@spec initialize_all_infra_components() :: {:ok, []} | {:error, term()}

Initialize all infrastructure components.

Sets up supervision and configuration for Fuse, Hammer, and Poolboy. This function should be called during application startup.

Examples

iex> Infrastructure.initialize_all_infra_components()
{:ok, []}

initialize_circuit_breaker(name)

@spec initialize_circuit_breaker(atom()) :: :ok | {:error, Foundation.Types.Error.t()}

Initialize a circuit breaker with default configuration.

Uses sensible defaults for failure threshold and recovery time.

Parameters

  • name - Atom identifier for the circuit breaker

Default Configuration

  • :failure_threshold - 5 failures
  • :recovery_time - 30,000 milliseconds (30 seconds)

Examples

:ok = Infrastructure.initialize_circuit_breaker(:default_breaker)

Returns

  • :ok - Circuit breaker initialized successfully
  • {:error, reason} - Initialization failed

initialize_circuit_breaker(name, config)

@spec initialize_circuit_breaker(atom(), map()) ::
  :ok | {:error, Foundation.Types.Error.t()}

Initialize a circuit breaker with the given configuration.

Creates and configures a circuit breaker that can be used with execute_protected. The circuit breaker will use the :fuse library for the actual circuit breaking logic.

Parameters

  • name - Atom identifier for the circuit breaker
  • config - Configuration map with required keys

Configuration Keys

  • :failure_threshold - Number of failures before opening circuit (required)
  • :recovery_time - Time in milliseconds before attempting recovery (required)

Examples

# Initialize with custom configuration
:ok = Infrastructure.initialize_circuit_breaker(:api_breaker, %{
  failure_threshold: 5,
  recovery_time: 30_000
})

# Use in execute_protected
Infrastructure.execute_protected(:api, [circuit_breaker: :api_breaker], fn ->
  # Your operation here
end)

Returns

  • :ok - Circuit breaker initialized successfully
  • {:error, reason} - Initialization failed

list_protection_keys()

@spec list_protection_keys() :: [protection_key()]

Lists all configured protection keys.

Returns

  • [protection_key] - List of configured protection keys