Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic modules #13

Merged
merged 3 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HOST=127.0.0.1
PORT=5001
DATABASE_URL="postgres://postgres:admin@localhost:5432/demo"
34 changes: 34 additions & 0 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ edition = "2021"
[dependencies]
anyhow = "1.0.75"
chrono = { version = "0.4.31", features = ["serde"] }
diesel = { version = "2.1.4", features = ["chrono", "postgres"] }
diesel = { version = "2.1.4", features = ["chrono", "postgres", "uuid", "r2d2"] }
dotenv = "0.15.0"
env_logger = "0.10.1"
salvo = { version = "0.58.3", features = ["cors", "anyhow", "logging"] }
once_cell = "1.18.0"
salvo = { version = "0.58.3", features = ["cors", "anyhow", "logging", "affix"] }
serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108"
tokio = { version = "1.34.0", features = ["macros"] }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
uuid = { version = "1.6.1", features = ["serde", "v4"] }
32 changes: 32 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: "3.9"

services:
db:
image: postgres:latest
container_name: localdb
restart: always
user: postgres
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=demo
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
ports:
- "5432:5432"
healthcheck:
test: [ "CMD", "pg_isready" ]
interval: 10s
timeout: 5s
retries: 5


volumes:
db-data:

secrets:
db-password:
file: db/pass.txt
1 change: 1 addition & 0 deletions db/pass.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
admin
2 changes: 1 addition & 1 deletion diesel.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# see diesel.rs/guides/configuring-diesel-cli

[print_schema]
file = "src/schema/schema.rs"
file = "src/schema.rs"
Empty file added migrations/.keep
Empty file.
6 changes: 6 additions & 0 deletions migrations/00000000000000_diesel_initial_setup/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.

DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
DROP FUNCTION IF EXISTS diesel_set_updated_at();
36 changes: 36 additions & 0 deletions migrations/00000000000000_diesel_initial_setup/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.




-- Sets up a trigger for the given table to automatically set a column called
-- `updated_at` whenever the row is modified (unless `updated_at` was included
-- in the modified columns)
--
-- # Example
--
-- ```sql
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
--
-- SELECT diesel_manage_updated_at('users');
-- ```
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
BEGIN
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
BEGIN
IF (
NEW IS DISTINCT FROM OLD AND
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
) THEN
NEW.updated_at := current_timestamp;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
2 changes: 2 additions & 0 deletions migrations/2023-11-20-073822_users/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE users
6 changes: 6 additions & 0 deletions migrations/2023-11-20-073822_users/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Your SQL goes here
CREATE TABLE users (
id uuid PRIMARY KEY default gen_random_uuid(),
name TEXT NOT NULL,
age INT NOT NULL
)
2 changes: 2 additions & 0 deletions migrations/2023-11-21-063116_users/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE users
6 changes: 6 additions & 0 deletions migrations/2023-11-21-063116_users/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- Your SQL goes here
CREATE TABLE users (
id uuid PRIMARY KEY default gen_random_uuid(),
name TEXT NOT NULL,
age INT NOT NULL
)
10 changes: 1 addition & 9 deletions src/common/database.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
use diesel::r2d2::{self, ConnectionManager, PooledConnection};
use once_cell::sync::OnceCell;

#[cfg(feature = "database_postgres")]
type DbCon = diesel::PgConnection;

#[cfg(all(feature = "database_postgres", debug_assertions))]
#[allow(dead_code)]
pub type DbCon = diesel::PgConnection;
pub type DieselBackend = diesel::pg::Pg;


pub type Pool = r2d2::Pool<ConnectionManager<DbCon>>;
pub type Connection = PooledConnection<ConnectionManager<DbCon>>;

Expand Down Expand Up @@ -36,9 +31,6 @@ impl Database {
}

fn get_or_init_pool() -> &'static Pool {
#[cfg(debug_assertions)]
crate::load_env_vars();

static POOL: OnceCell<Pool> = OnceCell::new();

POOL.get_or_init(|| {
Expand Down
1 change: 1 addition & 0 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod database;
1 change: 1 addition & 0 deletions src/controllers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod user_controller;
15 changes: 15 additions & 0 deletions src/controllers/user_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::services::user_service::UserService;
use salvo::prelude::*;

use crate::common::database::Database;

#[handler]
pub async fn all_users(
req: &mut Request,
depot: &mut Depot,
res: &mut Response,
) {
let mut connection = Database::new().get_connection();
let users = UserService::list(&mut connection).await;
res.render(Json(users));
}
23 changes: 21 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
mod common;
mod controllers;
mod models;
mod services;
mod schema;

use controllers::user_controller;
use dotenv::dotenv;
use salvo::prelude::*;
use std::env;

#[handler]
async fn hello() -> &'static str {
Expand All @@ -7,9 +16,19 @@ async fn hello() -> &'static str {

#[tokio::main]
async fn main() {
env::set_var("RUST_LOG", "debug");
tracing_subscriber::fmt().init();

let router = Router::new().get(hello);
let acceptor = TcpListener::new("127.0.0.1:5001").bind().await;
dotenv().ok();

let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env file");
let host = env::var("HOST").expect("HOST is not set in .env file");
let port = env::var("PORT").expect("PORT is not set in .env file");
let server_url = format!("{host}:{port}");

let router = Router::new()
.get(user_controller::all_users);
let acceptor = TcpListener::new(server_url).bind().await;

Server::new(acceptor).serve(router).await;
}
1 change: 1 addition & 0 deletions src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod user;
13 changes: 13 additions & 0 deletions src/models/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use serde::{Deserialize, Serialize};
use diesel::prelude::*;
use uuid::Uuid;

use crate::schema::users;

#[derive(Serialize, Deserialize, Queryable, Insertable)]
#[table_name = "users"]
pub struct User {
pub id: Uuid,
pub name: String,
pub age: i32,
}
9 changes: 9 additions & 0 deletions src/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @generated automatically by Diesel CLI.

diesel::table! {
users (id) {
id -> Uuid,
name -> Text,
age -> Int4,
}
}
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod user_service;
41 changes: 41 additions & 0 deletions src/services/user_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use diesel;
use diesel::prelude::*;
use uuid::Uuid;

use crate::common::database::Connection;
use crate::models::user::User;

use crate::schema::users;
use crate::schema::users::dsl::users as all_users;


pub struct UserService;

impl UserService {
pub async fn list(connection: &mut Connection) -> Vec<User> {
users::table.load::<User>(connection).unwrap()
}

pub async fn create(connection: &mut Connection, new_user: &User) -> User {
let data = User {
id: Uuid::new_v4(),
name: new_user.name.clone(),
age: new_user.age.clone()
};

let _result = diesel::insert_into(users::table).values(&data).execute(connection);

users::table
.order(users::id.desc())
.first(connection)
.unwrap()
}

pub async fn delete(connection: &mut Connection, user_id: Uuid) -> bool {
diesel::delete(users::table.find(user_id)).execute(connection).is_ok()
}

pub async fn delete_all(connection: &mut Connection) -> bool {
diesel::delete(all_users).execute(connection).is_ok()
}
}
Loading