SnmpKit.SnmpLib.Pool (snmpkit v0.6.4)
Connection pooling and session management for high-performance SNMP operations.
This module provides sophisticated connection pooling capabilities designed for applications that need to manage many concurrent SNMP operations efficiently. Based on patterns proven in the DDumb project for handling 100+ concurrent device polls.
Features
- Connection Pooling: Efficient reuse of UDP sockets across operations
- Session Management: Per-device session tracking with state management
- Load Balancing: Intelligent distribution of operations across pool workers
- Health Monitoring: Automatic detection and handling of unhealthy connections
- Performance Metrics: Built-in monitoring and performance tracking
- Graceful Degradation: Circuit breaker patterns for failing devices
Pool Strategies
FIFO Pool (Default)
Best for general-purpose SNMP operations with mixed device types.
Round-Robin Pool
Optimal for polling multiple devices with similar characteristics.
Device-Affinity Pool
Routes operations for the same device to the same worker for session consistency.
Usage Patterns
# Start a pool for network monitoring
{:ok, pool_pid} = SnmpKit.SnmpLib.Pool.start_pool(:network_monitor,
strategy: :device_affinity,
size: 20,
max_overflow: 10
)
# Perform operations through the pool
SnmpKit.SnmpLib.Pool.with_connection(:network_monitor, "192.168.1.1", fn conn ->
SnmpKit.SnmpLib.Manager.get_multi(conn.socket, "192.168.1.1", oids, conn.opts)
end)
# Get pool statistics
stats = SnmpKit.SnmpLib.Pool.get_stats(:network_monitor)
IO.inspect(stats.active_connections)
Performance Benefits
- 60-80% reduction in socket creation overhead
- Improved throughput for high-frequency polling
- Lower memory usage through connection reuse
- Better resource utilization with intelligent load balancing
Summary
Functions
Returns a connection to the pool after manual checkout.
Checks out a connection from the pool for manual management.
Returns a specification to start this module under a supervisor.
Removes unhealthy connections from the pool and replaces them.
Gets comprehensive statistics about the pool's performance and health.
Forces a health check on all connections in the pool.
Starts a new connection pool with the specified configuration.
Stops a connection pool and cleans up all resources.
Executes a function with a pooled connection, handling checkout/checkin automatically.
Types
@type connection() :: %{ socket: :gen_udp.socket(), pid: pid(), device: binary() | nil, last_used: integer(), health_status: :healthy | :degraded | :unhealthy, operation_count: non_neg_integer(), error_count: non_neg_integer() }
@type pool_name() :: atom()
@type pool_opts() :: [ strategy: pool_strategy(), size: pos_integer(), max_overflow: non_neg_integer(), checkout_timeout: pos_integer(), max_idle_time: pos_integer(), health_check_interval: pos_integer(), worker_opts: keyword() ]
@type pool_stats() :: %{ name: pool_name(), strategy: pool_strategy(), size: pos_integer(), active_connections: non_neg_integer(), idle_connections: non_neg_integer(), overflow_connections: non_neg_integer(), total_checkouts: non_neg_integer(), total_checkins: non_neg_integer(), health_status: map(), average_response_time: float() }
@type pool_strategy() :: :fifo | :round_robin | :device_affinity
Functions
@spec checkin_connection(pool_name(), connection()) :: :ok
Returns a connection to the pool after manual checkout.
Examples
:ok = SnmpKit.SnmpLib.Pool.checkin_connection(:snmp_pool, connection)
@spec checkout_connection(pool_name(), binary(), keyword()) :: {:ok, connection()} | {:error, any()}
Checks out a connection from the pool for manual management.
Use this when you need more control over connection lifecycle.
You must call checkin_connection/2
when done.
Examples
{:ok, conn} = SnmpKit.SnmpLib.Pool.checkout_connection(:snmp_pool, "192.168.1.1")
# ... perform operations with conn
:ok = SnmpKit.SnmpLib.Pool.checkin_connection(:snmp_pool, conn)
Returns a specification to start this module under a supervisor.
See Supervisor
.
@spec cleanup_unhealthy(pool_name()) :: :ok
Removes unhealthy connections from the pool and replaces them.
Examples
:ok = SnmpKit.SnmpLib.Pool.cleanup_unhealthy(:snmp_pool)
@spec get_stats(pool_name()) :: pool_stats()
Gets comprehensive statistics about the pool's performance and health.
Returns
A map containing:
- Connection counts (active, idle, overflow)
- Operation statistics (checkouts, checkins, response times)
- Health status for connections
- Performance metrics
Examples
stats = SnmpKit.SnmpLib.Pool.get_stats(:snmp_pool)
IO.puts("Active connections: " <> to_string(stats.active_connections))
IO.puts("Average response time: " <> to_string(stats.average_response_time) <> "ms")
@spec health_check(pool_name()) :: :ok
Forces a health check on all connections in the pool.
Useful for proactive monitoring and debugging connection issues.
Examples
:ok = SnmpKit.SnmpLib.Pool.health_check(:snmp_pool)
Starts a new connection pool with the specified configuration.
Parameters
pool_name
: Unique atom identifier for the poolopts
: Pool configuration options
Options
strategy
: Pool strategy (:fifo, :round_robin, :device_affinity)size
: Base number of connections in the pool (default: 10)max_overflow
: Maximum overflow connections allowed (default: 5)checkout_timeout
: Maximum time to wait for connection (default: 5000ms)max_idle_time
: Maximum idle time before connection cleanup (default: 300000ms)health_check_interval
: Interval for health checks (default: 30000ms)worker_opts
: Options passed to individual workers
Returns
{:ok, pid}
: Pool started successfully{:error, reason}
: Failed to start pool
Examples
# Basic pool for general SNMP operations
{:ok, _pid} = SnmpKit.SnmpLib.Pool.start_pool(:snmp_pool)
# High-performance pool for device monitoring
{:ok, _pid} = SnmpKit.SnmpLib.Pool.start_pool(:monitor_pool,
strategy: :device_affinity,
size: 25,
max_overflow: 15,
health_check_interval: 60_000
)
@spec stop_pool(pool_name(), pos_integer()) :: :ok
Stops a connection pool and cleans up all resources.
Parameters
pool_name
: Name of the pool to stoptimeout
: Maximum time to wait for graceful shutdown (default: 5000ms)
Examples
:ok = SnmpKit.SnmpLib.Pool.stop_pool(:snmp_pool)
:ok = SnmpKit.SnmpLib.Pool.stop_pool(:monitor_pool, 10_000)
Executes a function with a pooled connection, handling checkout/checkin automatically.
This is the primary interface for using pooled connections. The function automatically handles connection lifecycle and error recovery.
Parameters
pool_name
: Name of the pool to usedevice
: Target device (used for device-affinity strategy)fun
: Function to execute with the connectionopts
: Additional options for the operation
Returns
The result of executing the function, or {:error, reason}
if connection
checkout fails or the function raises an exception.
Examples
# Perform multiple operations with connection reuse
result = SnmpKit.SnmpLib.Pool.with_connection(:snmp_pool, "192.168.1.1", fn conn ->
{:ok, sys_desc} = SnmpKit.SnmpLib.Manager.get_with_socket(conn.socket, "192.168.1.1",
[1,3,6,1,2,1,1,1,0], conn.opts)
{:ok, sys_name} = SnmpKit.SnmpLib.Manager.get_with_socket(conn.socket, "192.168.1.1",
[1,3,6,1,2,1,1,5,0], conn.opts)
{:sys_desc, sys_desc, :sys_name, sys_name}
end)