diff --git a/async_pg/.gitignore b/async_pg/.gitignore index 53eaa219..37c8717f 100644 --- a/async_pg/.gitignore +++ b/async_pg/.gitignore @@ -1,2 +1,3 @@ /target **/*.rs.bk +.env diff --git a/async_pg/Cargo.toml b/async_pg/Cargo.toml index c7d81273..20706a55 100644 --- a/async_pg/Cargo.toml +++ b/async_pg/Cargo.toml @@ -4,13 +4,14 @@ version = "0.1.0" authors = ["dowwie "] edition = "2018" - [dependencies] actix-rt = "1.0.0" actix-web = "2.0.0" -deadpool-postgres = "0.4.3" +config = "0.10.1" +deadpool-postgres = "0.5.0" derive_more = "0.99.2" -serde = { version = "1.0.104", features=["derive"] } +dotenv = "0.15.0" +serde = { version = "1.0.104", features = ["derive"] } tokio-pg-mapper = "0.1.4" tokio-pg-mapper-derive = "0.1.4" tokio-postgres = "0.5.1" diff --git a/async_pg/README.md b/async_pg/README.md index 4cedd651..50d55aae 100644 --- a/async_pg/README.md +++ b/async_pg/README.md @@ -1,12 +1,43 @@ -This example illustrates: - - tokio_postgres - - use of tokio_pg_mapper for postgres data mapping - - deadpool_postgres for connection pooling +# async_pg example +## This example illustrates -# Instructions -1. Set up the testing database by running /sql/create_db.sh -2. `cargo run` -3. from the command line (linux), POST a user to the endpoint: - echo '{"email": "ferris@thecrab.com", "first_name": "ferris", "last_name": "crab", "username": "ferreal"}' | http -f --json --print h POST http://127.0.0.1:8080/users - - a unique constraint exists for username, so running this twice will return a 500 +- `tokio_postgres` +- use of `tokio_pg_mapper` for postgres data mapping +- `deadpool_postgres` for connection pooling +- `dotenv` + `config` for configuration + +## Instructions + +1. Set up the testing database by running the included script: + + ```shell + ./sql/create_db.sh + ``` + +2. Create `.env` file: + + ```ini + SERVER_ADDR=127.0.0.1:8080 + PG.USER=test_user + PG.PASSWD=testing + PG.HOST=127.0.0.1 + PG.PORT=5432 + PG.DBNAME=testing_db + PG.POOL.MAX_SIZE=16 + ``` + +3. Run the server: + + ```shell + cargo run + ``` + +4. Using a different terminal send a HTTP POST request to the running server: + + ```shell + echo '{"email": "ferris@thecrab.com", "first_name": "ferris", "last_name": "crab", "username": "ferreal"}' | http -f --json --print h POST http://127.0.0.1:8080/users + ``` + + A unique constraint exists for username, so sending this request twice + will return an internal server error (HTTP 500). diff --git a/async_pg/src/main.rs b/async_pg/src/main.rs index aa31f173..09bfb665 100644 --- a/async_pg/src/main.rs +++ b/async_pg/src/main.rs @@ -1,3 +1,20 @@ +mod config { + use serde::Deserialize; + pub use ::config::ConfigError; + #[derive(Deserialize)] + pub struct Config { + pub server_addr: String, + pub pg: deadpool_postgres::Config, + } + impl Config { + pub fn from_env() -> Result { + let mut cfg = ::config::Config::new(); + cfg.merge(::config::Environment::new())?; + cfg.try_into() + } + } +} + mod models { use serde::{Deserialize, Serialize}; use tokio_pg_mapper_derive::PostgresMapper; @@ -88,31 +105,25 @@ mod handlers { } use actix_web::{web, App, HttpServer}; -use deadpool_postgres::{Manager, Pool}; +use dotenv::dotenv; use handlers::add_user; -use tokio_postgres::{Config, NoTls}; +use tokio_postgres::NoTls; #[actix_rt::main] async fn main() -> std::io::Result<()> { - const SERVER_ADDR: &str = "127.0.0.1:8080"; + dotenv().ok(); - let pg_config = "postgres://test_user:testing@127.0.0.1:5432/testing_db" - .parse::() - .unwrap(); - - let pool = Pool::new( - Manager::new(pg_config, NoTls), - 16, // # of connections in pool - ); + let config = crate::config::Config::from_env().unwrap(); + let pool = config.pg.create_pool(NoTls).unwrap(); let server = HttpServer::new(move || { App::new() .data(pool.clone()) .service(web::resource("/users").route(web::post().to(add_user))) }) - .bind(SERVER_ADDR)? + .bind(config.server_addr.clone())? .run(); - println!("Server running at http://{}/", SERVER_ADDR); + println!("Server running at http://{}/", config.server_addr); server.await }