A generic connection pool for Rust

Related tags

Database r2d2
Overview

r2d2

CircleCI

A generic connection pool for Rust.

Documentation

Opening a new database connection every time one is needed is both inefficient and can lead to resource exhaustion under high traffic conditions. A connection pool maintains a set of open connections to a database, handing them out for repeated use.

r2d2 is agnostic to the connection type it is managing. Implementors of the ManageConnection trait provide the database-specific logic to create and check the health of connections.

A (possibly not exhaustive) list of adaptors for different backends:

Backend Adaptor Crate
rust-postgres r2d2-postgres
redis-rs use r2d2 feature of redis-rs
rust-memcache r2d2-memcache
rust-mysql-simple r2d2-mysql
rusqlite r2d2-sqlite
rusted-cypher r2d2-cypher
diesel diesel::r2d2 (docs)
couchdb r2d2-couchdb
mongodb (archived)
use official mongodb driver instead
r2d2-mongodb
(deprecated: official driver handles pooling internally)
odbc r2d2-odbc
jfs r2d2-jfs
oracle r2d2-oracle
ldap3 r2d2-ldap

Example

Using an imaginary "foodb" database.

use std::thread;

extern crate r2d2;
extern crate r2d2_foodb;

fn main() {
    let manager = r2d2_foodb::FooConnectionManager::new("localhost:1234");
    let pool = r2d2::Pool::builder()
        .max_size(15)
        .build(manager)
        .unwrap();

    for _ in 0..20 {
        let pool = pool.clone();
        thread::spawn(move || {
            let conn = pool.get().unwrap();
            // use the connection
            // it will be returned to the pool when it falls out of scope.
        })
    }
}

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

You might also like...
Streaming Network Overlay Connection Arbitration Tunnel

SNOCAT Streaming Network Overlay Connection Arbitration Tunnel snocat is a framework for forwarding streams across authenticated, encrypted QUIC tunne

Diesel async connection implementation

A async interface for diesel Diesel gets rid of the boilerplate for database interaction and eliminates runtime errors without sacrificing performance

An async executor based on the Win32 thread pool API

wae An async executor based on the Win32 thread pool API use futures::channel::oneshot; #[wae::main] async fn main() { let (tx, rx) = oneshot::ch

This represents staked SOL, and can be sold for wSOL in the wSOL/stSOL Liquidity Pool

This represents staked SOL, and can be sold for wSOL in the wSOL/stSOL Liquidity Pool (paying a fee to skip the unstaking cool-down period). The value of your stSOL holdings is automatically incremented each epoch when staking rewards are paid.

A lock-free, append-only atomic pool.

A lock-free, append-only atomic pool. This library implements an atomic, append-only collection of items, where individual items can be acquired and r

High-performance, lock-free local and concurrent object memory pool with automated allocation, cleanup, and verification.

Opool: Fast lock-free concurrent and local object pool Opool is a high-performance Rust library that offers a concurrent and local object pool impleme

Implementation of generic IBC queries in CosmWasm.

CosmWasm IBC Queries Implements generic IBC queries in CosmWasm. This implementation requires the same contract to be deployed on both chains wishing

🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL.

SQLx 🧰 The Rust SQL Toolkit Install | Usage | Docs Built with ❤️ by The LaunchBadge team SQLx is an async, pure Rust† SQL crate featuring compile-tim

Redis re-implemented in Rust.

rsedis Redis re-implemented in Rust. Why? To learn Rust. Use Cases rsedis does not rely on UNIX-specific features. Windows users can run it as a repla

Comments
  • drop idle connections immediately after the pool is dropped

    drop idle connections immediately after the pool is dropped

    I found that when the pool is dropped with some connections remain in lifetime, ALL idle connections will not drop until the connection checked out is dropped. Changing pool field in PooledConnection to Weak<SharedPool<M>> can fix this problem.

    For example:

    use std::{
        sync::RwLock,
        thread::sleep,
        time::{Duration, Instant},
    };
    
    use r2d2::{ManageConnection, Pool};
    
    struct FooConnection;
    
    impl FooConnection {
        fn new() -> FooConnection {
            println!("connection");
            FooConnection
        }
    }
    
    impl Drop for FooConnection {
        fn drop(&mut self) {
            println!("drop connection, t: {:?}", Instant::now());
        }
    }
    
    struct FooManager;
    
    impl ManageConnection for FooManager {
        type Connection = FooConnection;
        type Error = std::io::Error;
    
        fn connect(&self) -> Result<FooConnection, Self::Error> {
            Ok(FooConnection::new())
        }
    
        fn is_valid(&self, _: &mut FooConnection) -> Result<(), Self::Error> {
            Ok(())
        }
    
        fn has_broken(&self, _: &mut FooConnection) -> bool {
            false
        }
    }
    
    static POOL: RwLock<Option<Pool<FooManager>>> = RwLock::new(None);
    
    fn main() -> anyhow::Result<()> {
        let pool = r2d2::Pool::builder()
            .min_idle(Some(2))
            .max_size(4)
            .build(FooManager)?;
    
        *POOL.write().unwrap() = Some(pool);
    
        std::thread::spawn(|| {
            let _conn = POOL.read().unwrap().as_ref().unwrap().get().unwrap();
            sleep(Duration::from_secs(5));
            // <- all connections dropped here before our change
    
            // <- only `_conn` dropped here after our change
            // <- other idle connections will dropped eralier.
        });
        sleep(Duration::from_micros(5000));
    
        {
            let _ = POOL.write().unwrap().take();
            // <- all IDLE connections will dropped here after our change
        }
    
        sleep(Duration::from_secs(10));
        Ok(())
    }
    
    
    opened by name1e5s 0
  • Using behind proxychains

    Using behind proxychains

    Hi, I'm creating a DbPoolConnection by using

    let manager = ConnectionManager::<PgConnection>::new(self.database_url());
    r2d2::Pool::builder().build(manager).expect("Failed to create pool.")
    

    This however fails after a couple of seconds if the script is started with proxychains cargo run --release. Is there's a way to use the pool behind proxychains?

    opened by Corfucinas 1
  • Allow hooking on connection get-from-pool and release-to-pool

    Allow hooking on connection get-from-pool and release-to-pool

    In some cases, specific initialization/cleanup needs to be done around managed connections when fetching them from the pool and releasing them to the pool.

    e.g.:

    1. https://github.com/diesel-rs/diesel/issues/3252 with solution suggested here
    2. Attempting to close any open transaction on release-to-pool (solution where transactions are generally managed with RAII as suggested here have the issues described here).

    Currently this requires having custom wrappers around PooledConnection and Pool, which prevents from always using r2d2 directly (and requires reimplementing a whole bunch of traits on the wrappers).

    Something that would remove this need would be to add on_take_from_pool and on_release_to_pool hooks to CustomizeConnection (or another trait if we want backwards-compat.) and/or ManageConnection.

    That would solve 1. by allowing users to automatically open a test transaction on_take_from_pool and rolling it back on_release_to_pool (on_release_to_pool would have to be called before is_valid).

    That would solve 2. by allowing users (and/or implementors of ManageConnection) to automatically attempt closing any open transactions on_release_to_pool in any way they see fit.

    I would imagine the overhead of the CustomizeConnection one to be really-not-too-high despite the dynamic dispatch because that would be absolutely negligible compared with what we actually do with the connection. (And obviously the overhead of the ManageConnection one would be zero because the statically dispatched no-op would be optimized out.)

    Would that be something that makes sense and could potentially be added to r2d2?

    Thanks,

    opened by Ten0 8
  • Document relationship between `min_idle`, `idle_timeout` and `max_lifetime`

    Document relationship between `min_idle`, `idle_timeout` and `max_lifetime`

    Looking at the documentation of Builder doesn't currently help understand r2d2's behaviour, when trying to answer questions like "how do I make sure there's always at least one connection at any given instant".

    This is related to ivanceras/r2d2-sqlite#39: currently ::memory is basically broken (at least in the sense of pooling connection, every connection from the pool is independent).

    It's possible that sqlite's mode=memory could be used to fix the issue (at least in part, it has limitations still) but sqlite will automatically delete and release the database if it has no connections open, so for this to work properly there needs to be a way to configure the pool such that once the first connection has been created there is always at least one connection in the pool at any instant.

    opened by xmo-odoo 1
Releases(v0.8.10)
Owner
Steven Fackler
Steven Fackler
rust-mysql-simple support library for the r2d2 connection pool

r2d2-mysql rust-mysql-simple support library for the r2d2 connection pool.

outersky 44 Nov 1, 2022
Memcached support for the r2d2 connection pool (Rust)

Memcached support for the r2d2 connection pool (Rust)

川田 恵氏 (Kawada Keishi a.k.a megumish) 4 Jul 12, 2022
rust-postgres support library for the r2d2 connection pool

r2d2-postgres Documentation rust-postgres support library for the r2d2 connection pool. Example use std::thread; use r2d2_postgres::{postgres::NoTls,

Steven Fackler 128 Dec 26, 2022
LDAP support for the r2d2 connection pool

r2d2-ldap LDAP support for the r2d2 connection pool Install Add this to your Cargo.toml: [dependencies] r2d2-ldap = "0.1.1" Basic Usage use std::threa

Aitor Ruano 2 Nov 7, 2020
Oracle support for the r2d2 connection pool

r2d2-oracle The documentation can be found on docs.rs. Oracle support for the r2d2 connection pool. This fits in between the r2d2 connection manager a

Ralph Ursprung 7 Dec 14, 2022
ODBC adapter for r2d2 connection pool

ODBC adapter for r2d2 connection pool

Konstantin V. Salikhov 9 Nov 3, 2021
r2d2-couchdb: CouchDB support for the r2d2 connection pool

r2d2-couchdb: CouchDB support for the r2d2 connection pool

Pablo Aguiar 10 Dec 2, 2022
r2d2-cypher is a r2d2 connection pool for rusted-cypher

r2d2-cypher is a r2d2 connection pool for rusted-cypher

Markus Kohlhase 10 Oct 16, 2021
Quick Pool: High Performance Rust Async Resource Pool

Quick Pool High Performance Rust Async Resource Pool Usage DBCP Database Backend Adapter Version PostgreSQL tokio-postgres qp-postgres Example use asy

Seungjae Park 13 Aug 23, 2022
Lightweight async Redis client with connection pooling written in pure Rust and 100% memory safe

redi-rs (or redirs) redi-rs is a Lightweight Redis client with connection pooling written in Rust and 100% memory safe redi-rs is a Redis client writt

Oğuz Türkay 4 May 20, 2023