Connection Pool
Recipe | Crates | Categories |
---|---|---|
Create a Connection Pool |
Create a Connection Pool
deadpool
⮳ is a simple async pool for connections and objects of any type.
use deadpool::managed; #[derive(Debug)] enum Error { Fail, } struct Server; impl Server { async fn get_answer(&self) -> i32 { 42 } } struct Manager; impl managed::Manager for Manager { type Error = Error; type Type = Server; async fn create(&self) -> Result<Server, Error> { Ok(Server) } async fn recycle( &self, _: &mut Server, _: &managed::Metrics, ) -> managed::RecycleResult<Error> { Ok(()) } } type Pool = managed::Pool<Manager>; #[tokio::main] async fn main() -> anyhow::Result<()> { let mgr = Manager; let pool = Pool::builder(mgr).build()?; let conn = pool.get().await.map_err(|err| { anyhow::anyhow!("Could not retrieve from the Pool: {:?}", err) })?; let answer = conn.get_answer().await; assert_eq!(answer, 42); println!("The answer is {}", answer); Ok(()) }
Here is an example demonstrating the use of deadpool
⮳ to connect to a Postgres database:
use deadpool_postgres::Runtime; use dotenvy::dotenv; use tokio_postgres::NoTls; // Deadpool + Postgres example // `deadpool` is an async pool for connections and objects of any type. // `deadpool_postgres` implements a `deadpool` manager for `tokio-postgres` // and also provides a statement cache by wrapping `tokio_postgres::Client` and // `tokio_postgres::Transaction`. // Add to your `Config.toml`: // deadpool = "0.12.1" # or latest version // deadpool-postgres = { version = "0.14.1", features = ["serde"] } // Add you database's configuration to your `.env` file, for example: // PG__HOST=pg.example.com // PG__USER=john_doe // PG__PASSWORD=topsecret // PG__DBNAME=example // PG__POOL__MAX_SIZE=16 // PG__POOL__TIMEOUTS__WAIT__SECS=5 // PG__POOL__TIMEOUTS__WAIT__NANOS=0 #[derive(Debug, serde::Deserialize)] struct Config { pub pg: deadpool_postgres::Config, } impl Config { // With the `serde` feature enabled, we can read the configuration using the // `config` crate. pub fn from_env() -> Result<Self, config::ConfigError> { config::Config::builder() .add_source(config::Environment::default().separator("__")) .build()? .try_deserialize() } } #[tokio::main] async fn main() -> anyhow::Result<()> { // Loads the `.env` file from the current directory or parents. dotenv().ok(); // Hydrate the configuration from environment variables. let cfg = Config::from_env()?; // Creates a new `Pool` using the `deadpool_postgres::Config`. let pool = cfg.pg.create_pool(Some(Runtime::Tokio1), NoTls)?; // Retrieves an Object from this Pool or waits for one to become available let client = pool.get().await?; // Like `tokio_postgres::Client::prepare()`, but uses an existing // `Statement` from the `StatementCache` if possible let stmt = client.prepare_cached("SELECT version()").await?; let rows = client.query(&stmt, &[]).await?; for row in rows { let version: &str = row.get(0); println!("PostgreSQL version: {}", version); } Ok(()) }