Expand description
ยงConnection Pool
A flexible, high-performance, generic async connection pool for Rust with background cleanup and comprehensive logging.
ยงโจ Features
- ๐ High Performance: Background cleanup eliminates connection acquisition latency
- ๐ง Fully Generic: Support for any connection type (TCP, Database, HTTP, etc.)
- โก Async/Await Native: Built on tokio with modern async Rust patterns
- ๐ก๏ธ Thread Safe: Concurrent connection sharing with proper synchronization
- ๐งน Smart Cleanup: Configurable background task for expired connection removal
- ๐ Rich Logging: Comprehensive observability with configurable log levels
- ๐ Auto-Return: RAII-based automatic connection return to pool
- โฑ๏ธ Timeout Control: Configurable timeouts for connection creation
- ๐ฏ Type Safe: Compile-time guarantees with zero-cost abstractions
- ๐งฉ Extensible: Custom connection types and validation logic via the
ConnectionManagertrait - ๐ Versatile: Suitable for TCP, database, and any custom connection pooling
ยงQuick Start
Add connection-pool to your Cargo.toml:
[dependencies]
connection-pool = "0.2"
tokio = { version = "1.47", features = ["full"] }Then you can use the connection pool in your application:
// 1. Define your ConnectionManager
use connection_pool::{ConnectionManager, ConnectionPool};
use std::future::Future;
use std::pin::Pin;
use tokio::net::TcpStream;
#[derive(Clone)]
pub struct TcpConnectionManager {
pub address: std::net::SocketAddr,
}
impl ConnectionManager for TcpConnectionManager {
type Connection = TcpStream;
type Error = std::io::Error;
type CreateFut = Pin<Box<dyn Future<Output = Result<TcpStream, Self::Error>> + Send>>;
type ValidFut<'a> = Pin<Box<dyn Future<Output = bool> + Send + 'a>>;
fn create_connection(&self) -> Self::CreateFut {
let addr = self.address;
Box::pin(async move { TcpStream::connect(addr).await })
}
fn is_valid<'a>(&'a self, conn: &'a mut Self::Connection) -> Self::ValidFut<'a> {
Box::pin(async move {
// Lightweight socket check only; for real liveness use a protocol heartbeat.
conn.peer_addr().is_ok()
})
}
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
// 2. Create a connection pool
let manager = TcpConnectionManager { address: "127.0.0.1:8080".parse().unwrap() };
let pool = ConnectionPool::new(
Some(10), // max pool size
None, // default idle timeout
None, // default connection timeout
None, // default cleanup config
manager,
);
// 3. Acquire and use a connection
let mut conn = pool.clone().get_connection().await.unwrap();
use tokio::io::AsyncWriteExt;
conn.write_all(b"hello").await.unwrap();
Ok(())
}peer_addr() is only a cheap socket-level check. It can tell you whether the
stream still exists locally, but it does not prove that the remote service is
actually healthy or ready to speak your protocol.
If you need stronger validation, add an application-level heartbeat such as
ping/pong, and make is_valid send and verify that message instead of
touching the data stream with a read.
ยงAdvanced Usage
- You can pool any connection type (e.g. database, API client) by implementing the
ConnectionManagertrait. - For TCP, prefer a protocol-level health check when you need to prove the peer is responsive.
- See
examples/db_example.rsfor a custom type example.
ยงTesting
cargo testยง๐๏ธ Configuration Options
| Parameter | Description | Default |
|---|---|---|
max_size | Maximum number of connections | 10 |
max_idle_time | Connection idle timeout | 5 minutes |
connection_timeout | Connection creation timeout | 10 seconds |
cleanup_interval | Background cleanup interval | 30 seconds |
ยง๐๏ธ Architecture
The connection pool is now based on a single ConnectionManager abstraction:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ConnectionPool<M: Manager> โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข Holds a user-defined ConnectionManager โ
โ โข Manages a queue of pooled connections โ
โ โข Semaphore for max concurrent connections โ
โ โข Background cleanup for idle connections โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโดโโโโโโโโโโ
โ โ
โโโโโโโผโโโโโโ โโโโโโโโโโโผโโโโโโโโโ
โ Semaphore โ โ Background Task โ
โ (Limits โ โ (Cleans up idle โ
โ max conn)โ โ connections) โ
โโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโผโโโโโโโโโโโโโ
โ Connection Queue โ
โ (VecDeque) โ
โโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโผโโโโโโโโโโโโโ
โ PooledStream โ
โ (RAII wrapper โ
โ auto-returns) โ
โโโโโโโโโโโโโโโโโโโโยงKey Components
- Semaphore: Controls maximum concurrent connections
- Background Cleanup: Async task for removing expired connections
- Connection Queue: FIFO queue of available connections
- RAII Wrapper:
PooledStreamfor automatic connection return
ยง๐งช Testing
Run the examples to see the pool in action:
# Basic TCP example
cargo run --example echo_example
# Database connection example
cargo run --example db_example
# Background cleanup demonstration
cargo run --example background_cleanup_exampleยง๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
ยง๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
ยง๐ Links
Structsยง
- Cleanup
Config - Configuration for background cleanup task
- Connection
Pool - Connection pool
- Managed
Connection - Pooled managed stream, provided for the outer world usage
- TcpConnection
Manager - Example implementation for TcpStream
Enumsยง
- Pool
Error - Connection pool errors
Traitsยง
- Connection
Manager - Manager responsible for creating new
ConnectionManager::Connections or checking existing ones.
Type Aliasesยง
- TcpConnection
Pool - Convenience type aliases for TCP connections
- TcpManaged
Connection - Managed TCP stream