Skip to content

pool #

Connection Pool Module

This module provides a robust connection pooling implementation for managing reusable resources like database connections. It handles connection lifecycle, validation, and efficient resource allocation with minimal overhead.

Features

  • Connection Reuse: Efficiently manages reusable connections
  • Health Validation: Automatic connection validation
  • Dynamic Scaling: Adjusts pool size based on demand
  • Intelligent Eviction: Removes stale connections with priority-based cleanup
  • Statistics Tracking: Provides detailed pool metrics
  • Thread Safety: Fully concurrent-safe implementation
  • Graceful Shutdown: Clean resource termination
  • Dynamic Configuration: Runtime configuration updates

Connections can be acquired and returned while other threads read statistics or update the configuration, including on Windows. Call close() after these threads finish to stop the pool's background maintenance thread.

Basic Usage

Creating a Pool

import db.mysql
import pool
import time

// Define your connection factory function
fn create_conn() !&pool.ConnectionPoolable {
    config := mysql.Config{
        host:     '127.0.0.1'
        port:     3306
        username: 'root'
        password: '12345678'
        dbname:   'mysql'
    }
    db := mysql.connect(config)!
    return &db
}

// Configure pool parameters
config := pool.ConnectionPoolConfig{
    max_conns:      50
    min_idle_conns: 5
    max_lifetime:   2 * time.hour
    idle_timeout:   30 * time.minute
    get_timeout:    5 * time.second
}

// Create connection pool
mut my_pool := pool.new_connection_pool(create_conn, config)!

// Acquire connection
mut conn := my_pool.get()!

// Convert `conn` to a `mysql.DB` object
mut db := conn as mysql.DB

// Use connection `db`
// ... your operations ...
// db.exec()

// Return connection to pool
my_pool.put(conn)!

// When application exits
my_pool.close()

Configuration Options

Parameter Default Value Description
max_conns 20 Maximum connections in pool
min_idle_conns 5 Minimum idle connections to maintain
max_lifetime 1 hour Max connection lifetime
idle_timeout 30 minutes Idle connection timeout
get_timeout 5 seconds Connection acquisition timeout
retry_base_delay 1 second Base delay for connection retries
max_retry_delay 30 seconds Maximum retry delay
max_retry_attempts 5 Maximum connection creation attempts

Advanced Features

Dynamic Configuration Update

new_config := pool.ConnectionPoolConfig{
    max_conns: 100
    min_idle_conns: 10
    // ... other parameters ...
}

my_pool.update_config(new_config)!

Connection Recovery Signal

// After connection maintenance/outage
my_pool.signal_recovery_event()

Statistics Monitoring

stats := my_pool.stats()
println("Active connections: ${stats.active_conns}")
println("Idle connections: ${stats.idle_conns}")
println("Waiting clients: ${stats.waiting_clients}")

Implementation Notes

  1. Exponential Backoff: Connection creation uses exponential backoff with jitter
  2. Priority Eviction: Four priority levels for connection cleanup:
    • low: Routine maintenance
    • medium: Connection acquisition failure
    • high: Configuration changes
    • urgent: Connection recovery events
  3. Adaptive Cleanup: Maintenance thread dynamically adjusts processing frequency
  4. Wait Queue: Fair connection allocation to waiting clients
  5. Atomic Operations: Non-blocking statistics tracking

Performance Considerations

  • Use appropriate min_idle_conns to balance startup time and memory
  • Set max_lifetime according to your backend connection limits
  • Monitor creation_errors statistic to detect connection issues
  • Use evicted_count to identify connection health problems

Example Implementation

// ConnectionPoolable connection interface implementation
struct MyConnection {
    // Your connection state
}

fn (mut c MyConnection) validate() !bool {
    // Connection health check logic
    return true
}

fn (mut c MyConnection) close() ! {
    // Physical close logic
}

fn (mut c MyConnection) reset() ! {
    // Reset connection to initial state
}

fn new_connection_pool #

fn new_connection_pool(conn_factory fn () !&ConnectionPoolable, config ConnectionPoolConfig) !&ConnectionPool

new_connection_pool creates a new connection pool

interface ConnectionPoolable #

interface ConnectionPoolable {
	// validate checks if the connection is still usable
mut:
	validate() !bool
	// close terminates the physical connection
	close() !
	// reset returns the connection to initial state for reuse
	reset() !
}

ConnectionPoolable defines the interface for connection objects

enum EvictionPriority #

enum EvictionPriority {
	low    // Routine cleanup (connection return)
	medium // Connection get failure
	high   // Configuration change
	urgent // Database/Server recovery
}

EvictionPriority indicates urgency of connection cleanup

struct ConnectionPool #

struct ConnectionPool {
mut:
	config ConnectionPoolConfig
	// Lock order:
	// config_mutex > create_mutex > idle_pool_mutex > all_conns_mutex > wait_queue_mutex
	config_mutex     &sync.RwMutex @[required] // Guards configuration changes
	create_mutex     &sync.Mutex // Serializes connection creation
	idle_pool_mutex  &sync.RwMutex              @[required] // Protects idle connections
	all_conns_mutex  &sync.RwMutex              @[required] // Protects all connections map
	wait_queue_mutex &sync.RwMutex              @[required] // Protects wait queue
	is_closed        &stdatomic.AtomicVal[bool] @[required] // Pool shutdown flag
	stop_ch          chan bool             // Signals maintenance thread to stop
	eviction_ch      chan EvictionPriority // Eviction event channel
	cleanup_thread   thread                // Background maintenance thread
	wait_queue       []chan bool           // Client wait queue for connection acquisition
	conn_factory     fn () !&ConnectionPoolable @[required] // Creates new connections
	active_count     &stdatomic.AtomicVal[int]  @[required] // Currently checked-out connections
	created_at       time.Time                      // Pool creation timestamp
	all_conns        map[voidptr]&ConnectionWrapper // All tracked connections
	idle_pool        []&ConnectionWrapper           // Currently idle connections
	creation_errors  &stdatomic.AtomicVal[int] @[required] // Failed creation attempts
	evicted_count    &stdatomic.AtomicVal[int] @[required] // Connections forcibly removed
	creating_count   &stdatomic.AtomicVal[int] @[required] // Connections being created
}

ConnectionPool manages a pool of reusable connections

fn (ConnectionPool) get #

fn (mut p ConnectionPool) get() !&ConnectionPoolable

get acquires a connection from the pool with timeout

fn (ConnectionPool) put #

fn (mut p ConnectionPool) put(conn &ConnectionPoolable) !

put returns a connection to the pool

fn (ConnectionPool) close #

fn (mut p ConnectionPool) close()

close shuts down the connection pool and cleans up resources

fn (ConnectionPool) update_config #

fn (mut p ConnectionPool) update_config(config ConnectionPoolConfig) !

update_config changes the connection pool configuration

fn (ConnectionPool) signal_recovery_event #

fn (mut p ConnectionPool) signal_recovery_event()

signal_recovery_event notifies the pool of recovery event

fn (ConnectionPool) send_eviction #

fn (mut p ConnectionPool) send_eviction(priority EvictionPriority)

send_eviction triggers a cleanup event

fn (ConnectionPool) stats #

fn (mut p ConnectionPool) stats() ConnectionPoolStats

stats retrieves current connection pool statistics

struct ConnectionPoolConfig #

@[params]
struct ConnectionPoolConfig {
pub mut:
	max_conns          int           = 20               // Maximum allowed connections
	min_idle_conns     int           = 5                // Minimum idle connections to maintain
	max_lifetime       time.Duration = time.hour        // Max lifetime of a connection
	idle_timeout       time.Duration = 30 * time.minute // Time before idle connections are cleaned up
	get_timeout        time.Duration = 5 * time.second  // Max time to wait for a connection
	retry_base_delay   time.Duration = 1 * time.second  // Base delay for retry backoff
	max_retry_delay    time.Duration = 30 * time.second // Maximum delay for retry backoff
	max_retry_attempts int           = 5                // Maximum retry attempts
}

ConnectionPoolConfig holds configuration settings for the connection pool

struct ConnectionPoolStats #

struct ConnectionPoolStats {
pub:
	total_conns     int       // All managed connections
	active_conns    int       // Currently checked-out connections
	idle_conns      int       // Available connections
	waiting_clients int       // Clients waiting for a connection
	evicted_count   int       // Connections forcibly removed
	creation_errors int       // Failed creation attempts
	created_at      time.Time // When pool was created
	creating_count  int       // Connections being created
}

ConnectionPoolStats holds statistics about the pool