Snakepit.Config (Snakepit v0.6.10)

View Source

Configuration management for Snakepit pools.

Handles validation and normalization of pool configurations, supporting both legacy single-pool and new multi-pool configurations.

Backward Compatibility

Existing v0.5.x configurations continue to work:

# Legacy config (v0.5.x) - still works!
config :snakepit,
  pooling_enabled: true,
  adapter_module: Snakepit.Adapters.GRPCPython,
  pool_size: 100

New Multi-Pool Configuration (v0.6.0+)

config :snakepit,
  pools: [
    %{
      name: :default,
      worker_profile: :process,
      pool_size: 100,
      adapter_module: Snakepit.Adapters.GRPCPython
    },
    %{
      name: :hpc,
      worker_profile: :thread,
      pool_size: 4,
      threads_per_worker: 16
    }
  ]

Configuration Schema

Per-pool configuration options:

Required

  • name - Pool identifier (atom)
  • adapter_module - Adapter module

Profile Selection

  • worker_profile - :process or :thread (default: :process)

Common Options

  • pool_size - Number of workers
  • adapter_args - CLI arguments for adapter
  • adapter_env - Environment variables

Process Profile Specific

  • startup_batch_size - Workers per batch (default: 8)
  • startup_batch_delay_ms - Delay between batches (default: 750)

Thread Profile Specific

  • threads_per_worker - Thread pool size per worker
  • thread_safety_checks - Enable runtime checks

Lifecycle Management

  • worker_ttl - Time-to-live (:infinity or {value, :seconds/:minutes/:hours})
  • worker_max_requests - Max requests before recycling (:infinity or integer)

Heartbeat options are mirrored in snakepit_bridge.heartbeat.HeartbeatConfig, so any new keys added here must be added to the Python struct and documented in the heartbeat guides to keep both sides in sync.

Normalized Shape

Snakepit.Config.normalize_pool_config/1 converts user input into a canonical map that downstream components rely on. The resulting structure (documented under normalized_pool_config/0) always includes heartbeat defaults, adapter metadata, and profile-specific knobs so pool, worker supervisor, and diagnostics modules never have to pattern-match on partial user input.

Summary

Functions

Get configuration for a specific named pool.

Get and validate pool configurations from application environment.

Get the profile module for a pool configuration.

Returns the normalized default heartbeat configuration, merged with application env overrides.

Normalize a pool configuration by filling in defaults.

Check if a pool configuration is using the thread profile.

Validate a single pool configuration.

Types

normalized_pool_config()

@type normalized_pool_config() :: map()

pool_config()

@type pool_config() :: map()

Normalized pool configuration returned by normalize_pool_config/1.

%{
  name: atom(),
  worker_profile: :process | :thread,
  pool_size: pos_integer(),
  adapter_module: module(),
  adapter_args: list(),
  adapter_env: list(),
  pool_identifier: atom() | nil,
  worker_ttl: :infinity | {integer(), :seconds | :minutes | :hours},
  worker_max_requests: :infinity | pos_integer(),
  heartbeat: map(),
  # Profile-specific fields:
  startup_batch_size: pos_integer(),
  startup_batch_delay_ms: non_neg_integer(),
  threads_per_worker: pos_integer(),
  thread_safety_checks: boolean()
}

validation_result()

@type validation_result() :: {:ok, [pool_config()]} | {:error, term()}

Functions

get_pool_config(pool_name)

@spec get_pool_config(atom()) :: {:ok, pool_config()} | {:error, term()}

Get configuration for a specific named pool.

Returns {:ok, config} or {:error, reason}.

The error can be :pool_not_found if the pool doesn't exist, or any error from get_pool_configs/0 if there's a configuration issue.

Examples

iex> Snakepit.Config.get_pool_config(:default)
{:ok, %{name: :default, worker_profile: :process, ...}}

get_pool_configs()

@spec get_pool_configs() :: validation_result()

Get and validate pool configurations from application environment.

Supports both legacy single-pool and new multi-pool configurations.

Returns {:ok, [pool_configs]} or {:error, reason}.

Examples

# With legacy config
{:ok, [%{name: :default, worker_profile: :process, ...}]}

# With multi-pool config
{:ok, [%{name: :default, ...}, %{name: :hpc, ...}]}

get_profile_module(config)

@spec get_profile_module(pool_config()) :: module()

Get the profile module for a pool configuration.

Returns the module that implements the WorkerProfile behaviour.

Examples

iex> Snakepit.Config.get_profile_module(%{worker_profile: :process})
Snakepit.WorkerProfile.Process

iex> Snakepit.Config.get_profile_module(%{worker_profile: :thread})
Snakepit.WorkerProfile.Thread

heartbeat_defaults()

@spec heartbeat_defaults() :: map()

Returns the normalized default heartbeat configuration, merged with application env overrides.

This shape is shared with snakepit_bridge.heartbeat.HeartbeatConfig. When adding new keys, update both modules to keep the cross-language schema aligned.

normalize_pool_config(config)

@spec normalize_pool_config(map()) :: pool_config()

Normalize a pool configuration by filling in defaults.

Examples

iex> Snakepit.Config.normalize_pool_config(%{name: :test})
%{
  name: :test,
  worker_profile: :process,
  pool_size: 16,
  # ... other defaults
}

thread_profile?(config)

@spec thread_profile?(pool_config()) :: boolean()

Check if a pool configuration is using the thread profile.

Examples

iex> Snakepit.Config.thread_profile?(%{worker_profile: :thread})
true

iex> Snakepit.Config.thread_profile?(%{worker_profile: :process})
false

validate_pool_config(config)

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

Validate a single pool configuration.

Returns {:ok, normalized_config} or {:error, reason}.