From 6b4e97a5ded76508e0dca8c8bd4491ddc4136c2d Mon Sep 17 00:00:00 2001 From: "Anthony M. Bonafide" Date: Tue, 26 Mar 2024 22:18:28 -0400 Subject: [PATCH] Adding DB conncetion to subscription Signed-off-by: Anthony M. Bonafide --- Cargo.lock | 5 +++++ Cargo.toml | 11 ++++++++++- src/main.rs | 8 +++++++- src/routes/subscriptions.rs | 20 +++++++++++++++++++- src/startup.rs | 7 +++++-- tests/health_check.rs | 8 +++++++- 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1f0030..4d1e246 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2660,6 +2660,9 @@ name = "uuid" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", +] [[package]] name = "vcpkg" @@ -2960,11 +2963,13 @@ name = "zero2prod" version = "0.1.0" dependencies = [ "actix-web", + "chrono", "config", "reqwest", "serde", "sqlx", "tokio", + "uuid", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0d4122a..5f37c66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,20 @@ actix-web = "4" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } serde = { version = "1", features = ["derive"] } config = "0.14" +uuid = { version = "1", features = ["v4"] } +chrono = { version = "0.4.22", default-features = false, features = ["clock"] } [dependencies.sqlx] verion = "0.7" default-features = false -features = ["runtime-tokio-rustls", "macros", "postgres", "uuid","chrono","migrate"] +features = [ + "runtime-tokio-rustls", + "macros", + "postgres", + "uuid", + "chrono", + "migrate", +] [dev-dependencies] reqwest = "0.12" diff --git a/src/main.rs b/src/main.rs index 50457de..0128740 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,17 @@ use std::net::TcpListener; +use sqlx::{Connection, PgConnection}; use zero2prod::{configuration::get_configuration, run}; #[tokio::main] async fn main() -> Result<(), std::io::Error> { let config = get_configuration().expect("Failed to read configuration"); let address = format!("127.0.0.1:{}", config.application_port); + let config = get_configuration().expect("Failed to get configuration"); + let connection = PgConnection::connect(&config.database.connection_string()) + .await + .expect("Failed to connect to database"); + let listener = TcpListener::bind(address)?; - run(listener)?.await + run(listener, connection)?.await } diff --git a/src/routes/subscriptions.rs b/src/routes/subscriptions.rs index c98a7eb..2f50be9 100644 --- a/src/routes/subscriptions.rs +++ b/src/routes/subscriptions.rs @@ -1,4 +1,7 @@ use actix_web::{web, HttpResponse}; +use chrono::Utc; +use sqlx::PgConnection; +use uuid::Uuid; #[derive(serde::Deserialize, serde::Serialize)] pub struct FormData { @@ -6,6 +9,21 @@ pub struct FormData { email: String, } -pub async fn subscribe(_form: web::Form) -> HttpResponse { +pub async fn subscribe( + form: web::Form, + connection: web::Data, +) -> HttpResponse { + sqlx::query!( + r#" + INSERT INTO subscriptions (id, email, name, subscribed_at) + VALUES ($1, $2, $3, $4) + "#, + Uuid::new_v4(), + form.email, + form.name, + Utc::now() + ) + .execute(connection.get_ref()) + .await; HttpResponse::Ok().finish() } diff --git a/src/startup.rs b/src/startup.rs index 2418315..f1f3e0d 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -1,12 +1,15 @@ use crate::routes::{health_check, subscribe}; use actix_web::{dev::Server, web, App, HttpServer}; +use sqlx::PgConnection; use std::net::TcpListener; -pub fn run(tcp_listener: TcpListener) -> Result { - let server = HttpServer::new(|| { +pub fn run(tcp_listener: TcpListener, connection: PgConnection) -> Result { + let connection = web::Data::new(connection); + let server = HttpServer::new(move || { App::new() .route("/health_check", web::get().to(health_check)) .route("/subscribe", web::post().to(subscribe)) + .app_data(connection.clone()) }) .listen(tcp_listener)? .run(); diff --git a/tests/health_check.rs b/tests/health_check.rs index ed91e0d..30dfa23 100644 --- a/tests/health_check.rs +++ b/tests/health_check.rs @@ -79,7 +79,13 @@ async fn subscribe_returns_400_for_missing_form_data() { fn spawn_app() -> String { let listener = TcpListener::bind("127.0.0.1:0").expect("Failed to bind port"); let port = listener.local_addr().unwrap().port(); - let server = run(listener).expect("Failed to bind address"); + let config = get_configuration().expect("Failed to get configuration"); + let connection = PgConnection::connect(&config.database.connection_string()) + .await + .expect("Failed to connect to database"); + + let server = run(listener, connection).expect("Failed to bind address"); + let _server_run = tokio::spawn(server); std::mem::drop(_server_run); format!("http://127.0.0.1:{}", port)