From 8a82fd00aadbd1ecd93b3297b332a161a3944d0c Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Tue, 15 Jun 2021 22:25:41 +0200 Subject: [PATCH] Add bb8 connection pool example (#19) I figure this will be quite common. --- Cargo.toml | 3 ++ examples/bb8_connection_pool.rs | 55 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 examples/bb8_connection_pool.rs diff --git a/Cargo.toml b/Cargo.toml index ced7cc15..c4303170 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,10 +42,13 @@ headers = { optional = true, version = "0.3" } [dev-dependencies] askama = "0.10.5" +bb8 = "0.7.0" +bb8-postgres = "0.7.0" hyper = { version = "0.14", features = ["full"] } reqwest = { version = "0.11", features = ["json", "stream"] } serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.6.1", features = ["macros", "rt", "rt-multi-thread"] } +tokio-postgres = "0.7.2" tracing = "0.1" tracing-subscriber = "0.2" uuid = "0.8" diff --git a/examples/bb8_connection_pool.rs b/examples/bb8_connection_pool.rs new file mode 100644 index 00000000..9ecfc999 --- /dev/null +++ b/examples/bb8_connection_pool.rs @@ -0,0 +1,55 @@ +use awebframework::{extract::Extension, prelude::*, AddExtensionLayer}; +use bb8::Pool; +use bb8_postgres::PostgresConnectionManager; +use http::StatusCode; +use std::net::SocketAddr; +use tokio_postgres::NoTls; + +#[tokio::main] +async fn main() { + tracing_subscriber::fmt::init(); + + // setup connection pool + let manager = + PostgresConnectionManager::new_from_stringlike("host=localhost user=postgres", NoTls) + .unwrap(); + let pool = Pool::builder().build(manager).await.unwrap(); + + // build our application with some routes + let app = route("/", get(handler)).layer(AddExtensionLayer::new(pool)); + + // run it with hyper + let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); + tracing::debug!("listening on {}", addr); + app.serve(&addr).await.unwrap(); +} + +type ConnectionPool = Pool>; + +async fn handler( + Extension(pool): Extension, +) -> Result { + // We cannot get a connection directly via an extractor because + // `bb8::PooledConnection` contains a reference to the pool and + // `extract::FromRequest` cannot return types that contain references. + // + // So therefore we have to get a connection from the pool manually. + let conn = pool.get().await.map_err(internal_error)?; + + let row = conn + .query_one("select 1 + 1", &[]) + .await + .map_err(internal_error)?; + let two: i32 = row.try_get(0).map_err(internal_error)?; + + Ok(two.to_string()) +} + +/// Utility function for mapping any error into a `500 Internal Server Error` +/// response. +fn internal_error(err: E) -> (StatusCode, String) +where + E: std::error::Error, +{ + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) +}