Features
- Generic over any resource — pool connections, clients, threads, buffers, or anything else through one
Managertrait. - Min / max sizing —
min_idleresources are created up front and kept ready; the pool grows on demand up tomax_sizeand never beyond it. - Blocking acquisition with timeouts —
getwaits up to a configuredcreate_timeout;get_timeoutoverrides it per call, andtry_getnever blocks. - Validation-on-borrow — an optional
validatehook (a health-check callback) runs on checkout; a resource that fails is discarded and replaced transparently. - Idle & max-lifetime expiry — stale resources are dropped and replaced on their next checkout, bounded by
idle_timeoutandmax_lifetime. - RAII return — the
Pooledguard recycles and returns its resource automatically on drop. There is noreleaseto forget and no way to leak a resource. - Thread-safe and cheap to share —
PoolisSend + Syncand clones into another handle onto the same pool. - Runtime-agnostic, zero-dependency — no async runtime, no third-party crates.
no_std-aware — the crate root compiles withoutstd; the pool itself is behind the defaultstdfeature.
Installation
[]
= "0.5"
MSRV is Rust 1.75. The crate is edition 2021 and builds on Linux, macOS, and Windows.
Quick Start
Implement Manager for your resource, then build a pool and borrow from it:
use ;
use Infallible;
// Describe how to create, reset, and (optionally) validate the resource.
let pool = builder
.max_size
.min_idle
.build
.expect;
// Borrow a buffer; it returns to the pool when `buf` is dropped.
let mut buf = pool.get.expect;
buf.extend_from_slice;
assert_eq!;
How It Works
A pool owns up to max_size resources. Each checkout:
- Reuses an idle resource if one is available — after applying
max_lifetime,idle_timeout, and thevalidatehealth check. A resource that is too old, too stale, or invalid is dropped and the pool moves on. - Creates a new resource if none is idle and the pool has not reached
max_size. - Waits if the pool is saturated, until a resource is returned or the timeout elapses.
When a Pooled guard is dropped, its resource is passed to recycle and returned to the idle set. If recycling fails — or the pool has been closed — the resource is dropped instead and its slot is freed for a replacement.
Resource construction, validation, and recycling all run without the pool's internal lock held, so a slow create (opening a socket, say) never blocks other threads from returning resources. The lock guards only a small queue and a couple of counters.
Configuration
Configure through the Builder, or build a PoolConfig directly (for example, from a settings file).
| Setting | Default | Meaning |
|---|---|---|
max_size |
10 |
Upper bound on resources owned at once (idle + checked out). |
min_idle |
0 |
Resources created up front and kept ready. Must be ≤ max_size. |
create_timeout |
30s |
How long get waits when saturated. None waits indefinitely. |
idle_timeout |
None |
Replace a resource unused for this long, checked on next borrow. |
max_lifetime |
None |
Replace a resource older than this, checked on next borrow. |
use Duration;
use ;
# use Infallible;
# ;
#
let pool = builder
.max_size
.min_idle
.create_timeout
.idle_timeout
.max_lifetime
.build
.expect;
# let _ = pool;
Using It From Async
The pool has no async dependency and get blocks the calling thread. In an async
context, acquire on a blocking-friendly executor thread; the returned guard is
Send, so it may be held across .await points:
let pool = pool.clone;
let mut conn = spawn_blocking.await??;
// `conn` is usable across awaits here.
A native non-blocking async acquisition API is on the roadmap (see below).
API Overview
For the complete reference — every public item, its parameters, return values, error semantics, and runnable examples — see docs/API.md.
Manager— the trait you implement:create,recycle, and the optionalvalidatehealth check.Pool—builder/new,get/get_timeout/try_get,status,close,is_closed.Builder— fluent configuration.PoolConfig— limits and lifecycle policy.Pooled— the RAII guard, deref-coercing to your resource.Status—size,idle,in_use,max_size.Error—Backend,Timeout,Closed,InvalidConfig.
Cross-Platform Support
- Linux (x86_64, aarch64)
- macOS (x86_64, Apple Silicon)
- Windows (x86_64)
CI runs formatting, lints, tests, and rustdoc with -D warnings on all three
operating systems, across both the stable toolchain and the MSRV (1.75).
Testing
The suite covers every lifecycle path with unit tests, an eight-thread
concurrency test, proptest properties for the pool's invariants (the max_size
ceiling, the size == idle + in_use identity, reuse, and close semantics), and
doctests on every public item.
# Full suite (unit, integration, property, and doctests)
# Microbenchmarks for the acquire/return hot path
# Lints and formatting, as enforced in CI
Roadmap
pool-mod is fast-tracking to a stable 1.0. Property tests and hot-path
benchmarks landed in v0.5.0. Still planned before 1.0: a background reaper that
prunes idle resources eagerly rather than on next checkout, tracked benchmark
baselines, and the pre-1.0 hardening audit. See
.dev/ROADMAP.md.
Standards
- REPS governs every decision. See REPS.md.
- MSRV: Rust 1.75.
- Edition: 2021.
- Cross-platform: Linux, macOS, Windows.
License
Dual-licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.