Skip to content

Commit

Permalink
POSTGRESgit ap! LFG
Browse files Browse the repository at this point in the history
  • Loading branch information
NChitty committed Jan 15, 2024
1 parent e721acc commit 738d90a
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 15 deletions.
4 changes: 4 additions & 0 deletions lambda/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lambda/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ lambda_http = "0.9.0"
lambda_runtime = "0.9.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.111"
sqlx = { version = "0.7.3", features = ["runtime-tokio", "postgres"] }
sqlx = { version = "0.7.3", features = ["runtime-tokio", "macros", "postgres", "uuid"] }
tokio = { version = "1", features = ["macros"] }
tracing = { version = "0.1", features = ["log"] }
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }
Expand Down
2 changes: 1 addition & 1 deletion lambda/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ pub mod recipe;
pub mod services;

pub trait Repository<T>: Send + Sync {
fn find_by_id(&self, id: Uuid) -> Option<T>;
async fn find_by_id(&self, id: Uuid) -> Option<T>;
}
3 changes: 2 additions & 1 deletion lambda/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ async fn main() -> Result<(), Error> {
.without_time()
.init();

let recipe_service = services::recipes().await;
let app = Router::new()
.route("/", get(root))
.route("/ping", get(ping))
.nest("/recipes", services::recipes());
.nest("/recipes", recipe_service);

run(app).await
}
3 changes: 2 additions & 1 deletion lambda/src/recipe/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;

#[derive(Deserialize, Serialize)]
#[derive(Deserialize, FromRow, Serialize)]
pub struct Recipe {
id: Uuid,
name: String,
Expand Down
20 changes: 15 additions & 5 deletions lambda/src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use axum::Router;
use axum::routing::get;
use crate::services::recipes::TestRecipeRepository;
use axum::Router;

use crate::services::recipes::PostgresRecipeRepository;

mod recipes;

Expand All @@ -9,12 +10,21 @@ struct ApplicationContext<T> {
pub repo: T,
}

pub fn recipes() -> Router {
pub async fn recipes() -> Router {
let db_username = std::env::var("DB_USERNAME").unwrap_or_else(|_| "postgres".to_string());
let db_password = std::env::var("DB_PASSWORD").unwrap_or_else(|_| "password1234".to_string());
let db_host = std::env::var("DB_HOST").unwrap_or_else(|_| "db".to_string());
let db_port = std::env::var("DB_PORT").unwrap_or_else(|_| "5432".to_string());
let db_name = std::env::var("DB_NAME").unwrap_or_else(|_| "meal-planner".to_string());
let db_connection_str = format!(
"postgresql://{db_username}:{db_password}@{db_host}:{db_port}/{db_name}"
);

let recipe_context = ApplicationContext {
repo: TestRecipeRepository {}
repo: PostgresRecipeRepository::new(&db_connection_str).await,
};

Router::new()
.route("/:id", get(recipes::read_one::<TestRecipeRepository>))
.route("/:id", get(recipes::read_one::<PostgresRecipeRepository>))
.with_state(recipe_context)
}
42 changes: 36 additions & 6 deletions lambda/src/services/recipes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::time::Duration;

use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::Json;
use sqlx::postgres::PgPoolOptions;
use sqlx::{Error, PgPool, Postgres};
use uuid::Uuid;

use crate::recipe::Recipe;
Expand All @@ -10,12 +14,38 @@ use crate::Repository;
#[derive(Clone)]
pub(super) struct TestRecipeRepository {}

impl Repository<Recipe> for TestRecipeRepository {
fn find_by_id(&self, id: Uuid) -> Option<Recipe> {
if id.is_nil() {
return Some(Recipe::default());
#[derive(Clone)]
pub(super) struct PostgresRecipeRepository {
pool: PgPool,
}

impl PostgresRecipeRepository {
pub(super) async fn new(url: &str) -> Self {
let pool: PgPool = PgPoolOptions::new()
.max_connections(5)
.acquire_timeout(Duration::from_secs(3))
.connect(&url)
.await
.expect("Can\'t connect to database");

Self { pool }
}
}

impl Repository<Recipe> for PostgresRecipeRepository {
async fn find_by_id(&self, id: Uuid) -> Option<Recipe> {
let result: Result<Recipe, Error> = sqlx::query_as("SELECT * FROM recipes WHERE id = $1")
.bind(id)
.fetch_one(&self.pool)
.await;

match result {
Ok(recipe) => Some(recipe),
Err(err) => {
dbg!(err);
None
},
}
None
}
}

Expand All @@ -26,7 +56,7 @@ pub(super) async fn read_one<T>(
where
T: Repository<Recipe>,
{
if let Some(recipe) = state.repo.find_by_id(id) {
if let Some(recipe) = state.repo.find_by_id(id).await {
return Ok(Json(recipe));
}

Expand Down

0 comments on commit 738d90a

Please sign in to comment.