From e7a77d0ee29160c105337165a48f88517f453af8 Mon Sep 17 00:00:00 2001 From: Pratik Tripathy Date: Tue, 1 Dec 2020 04:15:28 +0530 Subject: [PATCH] Reorg-ed --- Cargo.lock | 21 -------- Cargo.toml | 1 - .../2020-11-29-201712_create_products/up.sql | 9 +++- .../2020-11-29-201716_create_orders/up.sql | 10 +++- src/api/mod.rs | 1 + src/api/product_controller.rs | 19 +++++++ src/{config.rs => config/db_pool.rs} | 10 ++-- src/config/mod.rs | 1 + src/main.rs | 36 ++++++------- src/models/mod.rs | 1 + src/models/product.rs | 52 +++++++++++++++++++ src/schema.rs | 32 ++++++++++++ src/utils/constants.rs | 13 +++++ src/utils/mod.rs | 2 + 14 files changed, 156 insertions(+), 52 deletions(-) rename src/{config.rs => config/db_pool.rs} (72%) create mode 100644 src/schema.rs create mode 100644 src/utils/constants.rs diff --git a/Cargo.lock b/Cargo.lock index 1c54826..a49f943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -273,7 +273,6 @@ dependencies = [ "dotenv", "env_logger", "lazy_static", - "listenfd", "log", "r2d2", "serde", @@ -962,17 +961,6 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" -[[package]] -name = "listenfd" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "492158e732f2e2de81c592f0a2427e57e12cd3d59877378fe7af624b6bbe0ca1" -dependencies = [ - "libc", - "uuid", - "winapi 0.3.9", -] - [[package]] name = "lock_api" version = "0.4.2" @@ -1861,15 +1849,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "uuid" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "vcpkg" version = "0.2.10" diff --git a/Cargo.toml b/Cargo.toml index f769c4d..6572464 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,6 @@ edition = "2018" [dependencies] actix-web = "3.3.0" actix-rt = "1.1.1" -listenfd = "0.3.3" dotenv = "0.15.0" log = "0.4.11" env_logger = "0.8.2" diff --git a/migrations/2020-11-29-201712_create_products/up.sql b/migrations/2020-11-29-201712_create_products/up.sql index 1597422..77c75b5 100644 --- a/migrations/2020-11-29-201712_create_products/up.sql +++ b/migrations/2020-11-29-201712_create_products/up.sql @@ -1,8 +1,13 @@ +create sequence products_productid_seq; + create table if not exists products ( productid integer not null constraint pk_products - primary key, + primary key DEFAULT nextval('products_productid_seq'), productname text not null, created_at timestamp not null default current_timestamp -); \ No newline at end of file +); + +alter sequence products_productid_seq +owned by products.productid; \ No newline at end of file diff --git a/migrations/2020-11-29-201716_create_orders/up.sql b/migrations/2020-11-29-201716_create_orders/up.sql index 852d4db..decf3e1 100644 --- a/migrations/2020-11-29-201716_create_orders/up.sql +++ b/migrations/2020-11-29-201716_create_orders/up.sql @@ -1,8 +1,14 @@ +create sequence orders_ordersid_seq; + + create table if not exists orders ( orderid integer not null constraint pk_orders - primary key, + primary key default nextval('orders_ordersid_seq'), customer_email text not null, created_at timestamp not null default current_timestamp -); \ No newline at end of file +); + +alter sequence orders_ordersid_seq +owned by orders.orderid; \ No newline at end of file diff --git a/src/api/mod.rs b/src/api/mod.rs index e69de29..33be58f 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -0,0 +1 @@ +pub mod product_controller; \ No newline at end of file diff --git a/src/api/product_controller.rs b/src/api/product_controller.rs index e69de29..f419c86 100644 --- a/src/api/product_controller.rs +++ b/src/api/product_controller.rs @@ -0,0 +1,19 @@ +use crate::models::product::Product; +use actix_web::{get, web, HttpResponse, Responder}; + +#[get("/products")] +async fn find_all() -> impl Responder { + let products = Product::find_all().expect("Error fetching all Products"); + HttpResponse::Ok().json(products) +} + +#[get("/product/{id}")] +async fn find(id: web::Path) -> impl Responder { + let product = Product::find(id.into_inner()).expect("Error fetching Product"); + HttpResponse::Ok().json(product) +} + +pub fn routes(cfg: &mut web::ServiceConfig) { + cfg.service(find_all); + cfg.service(find); +} diff --git a/src/config.rs b/src/config/db_pool.rs similarity index 72% rename from src/config.rs rename to src/config/db_pool.rs index 67f0322..7c711ef 100644 --- a/src/config.rs +++ b/src/config/db_pool.rs @@ -1,4 +1,4 @@ -use crate::api_error::ApiError; +use crate::utils::api_error::ApiError; use diesel::pg::PgConnection; use diesel::r2d2::ConnectionManager; use lazy_static::lazy_static; @@ -14,18 +14,18 @@ lazy_static! { static ref POOL: Pool = { let db_url = env::var("DATABASE_URL").expect("Database url not set"); let manager = ConnectionManager::::new(db_url); - Pool::new(manager).expect("Failed to create db pool") + Pool::new(manager).expect("Failed to create config pool") }; } pub fn init() { info!("Initializing DB"); lazy_static::initialize(&POOL); - let conn = connection().expect("Failed to get db connection"); + let conn = get_connection().expect("Failed to get config connection"); embedded_migrations::run(&conn).unwrap(); } -pub fn connection() -> Result { +pub fn get_connection() -> Result { POOL.get() - .map_err(|e| ApiError::new(500, format!("Failed getting db connection: {}", e))) + .map_err(|e| ApiError::new(500, format!("Failed getting config connection: {}", e))) } \ No newline at end of file diff --git a/src/config/mod.rs b/src/config/mod.rs index e69de29..9c771a7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -0,0 +1 @@ +pub mod db_pool; diff --git a/src/main.rs b/src/main.rs index ee8e986..e4b1a12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,36 +7,30 @@ extern crate diesel_migrations; use actix_web::{App, HttpServer}; use dotenv::dotenv; -use listenfd::ListenFd; use std::env; +use crate::api::product_controller; +use config::db_pool; -mod db; -mod product; mod schema; -mod api_error; +mod utils; +mod models; +mod api; +mod config; #[actix_rt::main] async fn main() -> std::io::Result<()> { dotenv().ok(); env_logger::init(); - db::init(); - - let mut listenfd = ListenFd::from_env(); - let mut server = HttpServer::new(|| - App::new() - .configure(product::init_routes) - ); - - server = match listenfd.take_tcp_listener(0)? { - Some(listener) => server.listen(listener)?, - None => { - let host = env::var("HOST").expect("Host not set in .env file"); - let port = env::var("PORT").expect("Port not set in .env file"); - server.bind(format!("{}:{}", host, port))? - }, - }; + db_pool::init(); + let bind_address = format!("{}:{}", + env::var("HOST").expect("Host not set in .env file"), + env::var("PORT").expect("Port not set in .env file")); info!("Starting Server"); - server.run().await + HttpServer::new(|| + App::new() + .configure(product_controller::routes) + ).bind(bind_address)? + .run().await } diff --git a/src/models/mod.rs b/src/models/mod.rs index e69de29..1b2fa7a 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -0,0 +1 @@ +pub mod product; \ No newline at end of file diff --git a/src/models/product.rs b/src/models/product.rs index e69de29..50db449 100644 --- a/src/models/product.rs +++ b/src/models/product.rs @@ -0,0 +1,52 @@ +use crate::config::db_pool; +use crate::schema::products; +use chrono::{NaiveDateTime, Utc}; +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; +use crate::utils::api_error::ApiError; + +#[derive(Serialize, Deserialize, AsChangeset)] +#[table_name = "products"] +pub struct ProductMessage { + pub productid: i32, + pub productname: String, +} + +#[derive(Serialize, Deserialize, Queryable, Insertable)] +#[table_name = "products"] +pub struct Product { + pub productid: i32, + pub productname: String, + pub created_at: NaiveDateTime +} + +impl Product { + pub fn find_all() -> Result, ApiError> { + let conn = db_pool::get_connection()?; + + let products = products::table + .load::(&conn)?; + + Ok(products) + } + + pub fn find(id: i32) -> Result { + let conn = db_pool::get_connection()?; + + let product = products::table + .filter(products::productid.eq(id)) + .first(&conn)?; + + Ok(product) + } +} + +impl From for Product { + fn from(product: ProductMessage) -> Self { + Product { + productid: product.productid, + productname: product.productname, + created_at: Utc::now().naive_utc(), + } + } +} \ No newline at end of file diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..1c75438 --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,32 @@ +table! { + order_details (orderid, productid) { + orderid -> Int4, + productid -> Int4, + quantity -> Int4, + } +} + +table! { + orders (orderid) { + orderid -> Int4, + customer_email -> Text, + created_at -> Timestamp, + } +} + +table! { + products (productid) { + productid -> Int4, + productname -> Text, + created_at -> Timestamp, + } +} + +joinable!(order_details -> orders (orderid)); +joinable!(order_details -> products (productid)); + +allow_tables_to_appear_in_same_query!( + order_details, + orders, + products, +); diff --git a/src/utils/constants.rs b/src/utils/constants.rs new file mode 100644 index 0000000..89640f6 --- /dev/null +++ b/src/utils/constants.rs @@ -0,0 +1,13 @@ +// Messages +// pub const MESSAGE_OK: &str = "ok"; +// pub const MESSAGE_CAN_NOT_FETCH_DATA: &str = "Can not fetch data"; +// pub const MESSAGE_CAN_NOT_INSERT_DATA: &str = "Can not insert data"; +// pub const MESSAGE_CAN_NOT_UPDATE_DATA: &str = "Can not update data"; +// pub const MESSAGE_CAN_NOT_DELETE_DATA: &str = "Can not delete data"; +// pub const MESSAGE_INTERNAL_SERVER_ERROR: &str = "Internal Server Error"; +// +// // Misc +// pub const EMPTY: &str = ""; +// +// // ignore routes +// pub const IGNORE_ROUTES: [&str; 3] = ["/api/ping", "/api/auth/signup", "/api/auth/login"]; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index e69de29..d0f1c8d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod api_error; +pub mod constants;