Foundation.Infrastructure.RateLimiter (foundation v0.1.0)

Rate limiter wrapper around Hammer library.

Provides standardized rate limiting functionality with telemetry integration and Foundation-specific error handling. Translates Hammer responses to Foundation.Types.Error structures.

Usage

# Check if request is allowed
case RateLimiter.check_rate("user:123", :login, 5, 60_000) do
  :ok -> proceed_with_request()
  {:error, error} -> handle_rate_limit(error)
end

# Get current rate status
status = RateLimiter.get_status("user:123", :login)

Summary

Functions

Check if a request is allowed under rate limiting constraints.

Get the current rate limiting status for an entity and operation.

Reset the rate limiting bucket for an entity and operation.

Types

entity_id()

@type entity_id() :: String.t() | atom() | integer()

operation()

@type operation() :: atom()

rate_check_result()

@type rate_check_result() :: :ok | {:error, Foundation.Types.Error.t()}

rate_limit()

@type rate_limit() :: pos_integer()

time_window()

@type time_window() :: pos_integer()

Functions

check_rate(entity_id, operation, limit, time_window_ms, metadata \\ %{})

@spec check_rate(entity_id(), operation(), rate_limit(), time_window(), map()) ::
  rate_check_result()

Check if a request is allowed under rate limiting constraints.

Parameters

  • entity_id: Identifier for the entity being rate limited (user, IP, etc.)
  • operation: Type of operation being performed
  • limit: Maximum number of requests allowed
  • time_window_ms: Time window in milliseconds
  • metadata: Additional telemetry metadata

Examples

iex> RateLimiter.check_rate("user:123", :api_call, 100, 60_000)
:ok

iex> RateLimiter.check_rate("user:456", :heavy_operation, 5, 60_000)
{:error, %Error{error_type: :rate_limit_exceeded}}

execute_with_limit(entity_id, operation_name, limit, time_window_ms, operation_fun, metadata \\ %{})

@spec execute_with_limit(
  entity_id(),
  operation(),
  rate_limit(),
  time_window(),
  (-> any()),
  map()
) ::
  {:ok, any()} | {:error, Foundation.Types.Error.t()}

Execute an operation with rate limiting protection.

Parameters

  • entity_id: Identifier for the entity
  • operation_name: Type of operation for rate limiting
  • limit: Maximum number of requests allowed
  • time_window_ms: Time window in milliseconds
  • operation_fun: Function to execute if allowed
  • metadata: Additional telemetry metadata

Examples

iex> RateLimiter.execute_with_limit("user:123", :api_call, 100, 60_000, fn ->
...>   expensive_api_call()
...> end)
{:ok, result}

get_status(entity_id, operation)

@spec get_status(entity_id(), operation()) :: {:ok, map()}

Get the current rate limiting status for an entity and operation.

This is a simplified implementation that doesn't provide detailed bucket information.

Parameters

  • entity_id: Identifier for the entity
  • operation: Type of operation

Returns

  • {:ok, %{status: :available | :rate_limited}}

  • {:error, Error.t()}

Examples

iex> RateLimiter.get_status("user:123", :api_call)
{:ok, %{status: :available}}

reset(entity_id, operation)

@spec reset(entity_id(), operation()) :: :ok | {:error, Foundation.Types.Error.t()}

Reset the rate limiting bucket for an entity and operation.

Note: This is a simplified implementation that may not actually clear the bucket depending on the Hammer backend configuration.

Parameters

  • entity_id: Identifier for the entity
  • operation: Type of operation

Examples

iex> RateLimiter.reset("user:123", :api_call)
:ok