diff --git a/backend/server/build.rs b/backend/server/build.rs index b7d91af..aae7d8b 100644 --- a/backend/server/build.rs +++ b/backend/server/build.rs @@ -9,7 +9,8 @@ fn main() { .peel_to_commit() .expect("failed to get HEAD commit"); let hash = commit.id().to_string(); - let utc_date = Utc::now().date_naive().format("%Y%m%d").to_string(); - let build_id = format!("{}@{}", utc_date, &hash[..8]); + let utc_timestamp = Utc::now().date_naive().format("%Y%m%d").to_string(); + let pkg_version = env!("CARGO_PKG_VERSION"); + let build_id = format!("{}:{}@{}", pkg_version, &hash[..8], utc_timestamp); println!("cargo:rustc-env=BUILD_ID={}", build_id); } diff --git a/backend/server/schema.sql b/backend/server/schema.sql deleted file mode 100644 index 675175e..0000000 --- a/backend/server/schema.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE tag -( - id SERIAL PRIMARY KEY, - name VARCHAR(20) UNIQUE NOT NULL, - description TEXT -); - -CREATE TABLE category -( - id SERIAL PRIMARY KEY, - name VARCHAR(20) UNIQUE NOT NULL, - description TEXT -); - -CREATE TABLE post -( - id SERIAL PRIMARY KEY, - identifier VARCHAR(50) UNIQUE NOT NULL, - title VARCHAR(255) NOT NULL, - subtitle VARCHAR(255) NOT NULL, - published_date DATE NOT NULL, - last_update DATE, - content TEXT NOT NULL, - - category SERIAL REFERENCES category (id) NOT NULL -); - -CREATE TABLE post_tag -( - post SERIAL REFERENCES post (id), - tag SERIAL REFERENCES tag (id) -) \ No newline at end of file diff --git a/backend/server/src/init/mod.rs b/backend/server/src/init/mod.rs index 4da997a..465d530 100644 --- a/backend/server/src/init/mod.rs +++ b/backend/server/src/init/mod.rs @@ -1,7 +1,6 @@ mod database; pub mod logger; mod misc; -mod schema; use std::{env, panic}; diff --git a/backend/server/src/init/schema.rs b/backend/server/src/init/schema.rs deleted file mode 100644 index 6cd1363..0000000 --- a/backend/server/src/init/schema.rs +++ /dev/null @@ -1,49 +0,0 @@ -use sqlx::{query, Pool, Postgres}; -use tracing::info; -// -// const POST_BASE_MODEL: &str = r##" -// CREATE TABLE IF NOT EXISTS Post -// ( -// post_id UUID PRIMARY KEY, -// title VARCHAR(255) NOT NULL, -// category VARCHAR(255) NOT NULL, -// filename TEXT UNIQUE NOT NULL, -// summary TEXT, -// sub_title TEXT, -// content TEXT NOT NULL, -// last_update TIMESTAMPTZ, -// first_update TIMESTAMPTZ NOT NULL -// ); -// "##; -// -// // base model, will add more cols at runtime -// const POST_META_MODEL: &str = r##" -// CREATE TABLE IF NOT EXISTS Meta -// ( -// post_id UUID PRIMARY KEY -// ); -// "##; -// -// const POST_HASH_MODEL: &str = r##" -// CREATE TABLE IF NOT EXISTS Hash -// ( -// post_id UUID PRIMARY KEY, -// hash VARCHAR(44) -// ); -// "##; -// -// const TAG_MODEL: &str = r##" -// CREATE TABLE IF NOT EXISTS Tag -// ( -// post_id UUID NOT NULL, -// tag VARCHAR(255) NOT NULL -// ); -// "##; - -pub async fn init(db_connection: &Pool) { - // query(POST_BASE_MODEL).execute(db_connection).await.unwrap(); - // query(POST_META_MODEL).execute(db_connection).await.unwrap(); - // query(TAG_MODEL).execute(db_connection).await.unwrap(); - // query(POST_HASH_MODEL).execute(db_connection).await.unwrap(); - info!("database schema initialized"); -} diff --git a/backend/server/src/main.rs b/backend/server/src/main.rs index 8971580..04e2712 100644 --- a/backend/server/src/main.rs +++ b/backend/server/src/main.rs @@ -1,7 +1,11 @@ +#[allow(dead_code)] mod constants; + +#[allow(dead_code)] +mod scheduler; + mod init; mod modules; -mod scheduler; mod utils; use crate::init::{logger, start}; diff --git a/backend/server/src/modules/blog/api/get_page_count.rs b/backend/server/src/modules/blog/api/get_page_count.rs deleted file mode 100644 index 771098f..0000000 --- a/backend/server/src/modules/blog/api/get_page_count.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::constants::blog::PAGE_SIZE; - -use axum::extract::State; -use axum::Json; -use serde_json::{json, Value}; -use sqlx::{query, PgPool, Row}; -use tracing::error; - -pub async fn get_page_count( - State(db_connection): State, -) -> Result, Json> { - match query("select cast(ceil(count(*) / $1) as integer) as res from post") - .bind(PAGE_SIZE as f32) - .fetch_one(&db_connection) - .await - { - Ok(res) => { - let res: i32 = res.get("res"); - Ok(Json::from(json!({"res": res}))) - } - Err(e) => { - // todo: rename - error!("Failed to get blog page count: {}", e.to_string()); - Err(Json::from(json!({"error": e.to_string()}))) - } - } -} diff --git a/backend/server/src/modules/blog/api/get_page_count/mod.rs b/backend/server/src/modules/blog/api/get_page_count/mod.rs new file mode 100644 index 0000000..c27a427 --- /dev/null +++ b/backend/server/src/modules/blog/api/get_page_count/mod.rs @@ -0,0 +1,25 @@ +use crate::constants::blog::PAGE_SIZE; + +use axum::{extract::State, Json}; +use serde_json::{json, Value}; +use sqlx::{query, PgPool, Row}; +use tracing::error; + +const GET_PAGE_COUNT_QUERY: &str = include_str!("post_page_count.sql"); + +pub async fn handler(State(db_connection): State) -> Result, Json> { + match query(GET_PAGE_COUNT_QUERY) + .bind(PAGE_SIZE as i64) + .fetch_one(&db_connection) + .await + { + Ok(res) => { + let res: i32 = res.get("count"); + Ok(Json::from(json!({"res": res}))) + } + Err(e) => { + error!("failed to get blog page count: {}", e.to_string()); + Err(Json::from(json!({"error": e.to_string()}))) + } + } +} diff --git a/backend/server/src/modules/blog/api/get_page_count/post_page_count.sql b/backend/server/src/modules/blog/api/get_page_count/post_page_count.sql new file mode 100644 index 0000000..5ccce6b --- /dev/null +++ b/backend/server/src/modules/blog/api/get_page_count/post_page_count.sql @@ -0,0 +1,2 @@ +SELECT cast(ceil(count(*) / cast($1 AS FLOAT)) AS INTEGER) AS count +FROM posts; diff --git a/backend/server/src/modules/blog/api/get_post.rs b/backend/server/src/modules/blog/api/get_post.rs deleted file mode 100644 index 2374dec..0000000 --- a/backend/server/src/modules/blog/api/get_post.rs +++ /dev/null @@ -1,153 +0,0 @@ -use axum::{ - extract::{Path, State}, - http::StatusCode, - Json, -}; -use serde_json::{json, Value}; -use sqlx::{query, Error, PgPool, Row}; -use std::str::FromStr; -use tracing::error; -use uuid::Uuid; - -pub async fn get_post( - State(db_connection): State, - Path(post_id): Path, -) -> Result, (StatusCode, Json)> { - let post_id = match Uuid::from_str(post_id.as_str()) { - Ok(id) => id, - Err(e) => { - error!( - "Failed to parse UUID <{}>: {}", - post_id.as_str(), - e.to_string() - ); - return Err(( - StatusCode::BAD_REQUEST, - Json::from(json!(("error", e.to_string()))), - )); - } - }; - - let post = match query( - r#" -SELECT jsonb_strip_nulls(to_jsonb(t.*)) - 'post_id' AS post -FROM post t -WHERE post_id = $1; -"#, - ) - .bind(post_id) - .fetch_one(&db_connection) - .await - { - Ok(value) => value.get::("post"), - Err(e) => { - error!( - "Database error on Reading `base post information` from table `post`: <{}>: {}", - post_id.to_string(), - e.to_string() - ); - return match e { - Error::RowNotFound => Err(( - StatusCode::BAD_REQUEST, - Json::from(json!({"error": e.to_string()})), - )), - _ => Err(( - StatusCode::INTERNAL_SERVER_ERROR, - Json::from(json!({"error": e.to_string()})), - )), - }; - } - }; - - let tags: Vec<_> = match query("SELECT tag FROM Tag WHERE post_id = $1;") - .bind(post_id) - .fetch_all(&db_connection) - .await - { - Ok(tags) => tags.iter().map(|tag| tag.get::("tag")).collect(), - Err(e) => { - error!("Database query error :{}", e.to_string()); - return Err(( - StatusCode::INTERNAL_SERVER_ERROR, - Json::from(json!({"error": e.to_string()})), - )); - } - }; - - let meta = match query( - r#" -SELECT jsonb_strip_nulls(to_jsonb(t.*)) - 'post_id' AS meta -FROM meta t -WHERE post_id = $1; - "#, - ) - .bind(post_id) - .fetch_one(&db_connection) - .await - { - Ok(value) => value.get::("meta"), - Err(e) => { - error!( - "Database error on Reading `{}` from table `{}`: <{}>: {}", - "post meta data", - "meta", - post_id.to_string(), - e.to_string() - ); - return Err(( - StatusCode::INTERNAL_SERVER_ERROR, - Json::from(json!({"error": e.to_string()})), - )); - } - }; - - let adjacent = match query(r" -WITH target_post AS (SELECT t.date FROM meta t WHERE post_id = $1), - prev AS (SELECT post_id, t.title, t.sub_title, t.header_img - FROM meta t - WHERE t.date < (SELECT date FROM target_post) - ORDER BY t.date DESC - LIMIT 1), - next AS (SELECT post_id, t.title, t.sub_title, t.header_img - FROM meta t - WHERE t.date > (SELECT date FROM target_post) - ORDER BY t.date - LIMIT 1) -SELECT json_strip_nulls(json_build_object( - 'prev', - (SELECT json_build_object('id', post_id, 'title', title, 'sub_title', sub_title, 'header_img', header_img) - FROM prev), - 'next', - (SELECT json_build_object('id', post_id, 'title', title, 'sub_title', sub_title, 'header_img', header_img) - FROM next) - )) AS result; -" - ) - .bind(post_id) - .fetch_one(&db_connection) - .await - { - Ok(res) => {res.get::("result")} - Err(e) => { - error!( - "Database error on Reading `{}` from table `{}`: <{}>: {}", - "adjoint posts data", - "meta", - post_id.to_string(), - e.to_string() - ); - return Err(( - StatusCode::INTERNAL_SERVER_ERROR, - Json::from(json!({"error": e.to_string()})), - )); - } - - }; - - let mut res = post.as_object().unwrap().to_owned(); - res.insert("tags".to_string(), tags.into()); - res.insert("meta".to_string(), meta); - res.insert("adj".to_string(), adjacent); - - Ok(Json::from(json!(res))) -} diff --git a/backend/server/src/modules/blog/api/get_post/get_post_by_i64_id.sql b/backend/server/src/modules/blog/api/get_post/get_post_by_i64_id.sql new file mode 100644 index 0000000..e69de29 diff --git a/backend/server/src/modules/blog/api/get_post/get_post_by_str_id.sql b/backend/server/src/modules/blog/api/get_post/get_post_by_str_id.sql new file mode 100644 index 0000000..e69de29 diff --git a/backend/server/src/modules/blog/api/get_post/mod.rs b/backend/server/src/modules/blog/api/get_post/mod.rs new file mode 100644 index 0000000..a9dd943 --- /dev/null +++ b/backend/server/src/modules/blog/api/get_post/mod.rs @@ -0,0 +1,30 @@ +use axum::response::IntoResponse; +use axum::{ + extract::{Path, State}, + Json, +}; +use serde_json::json; +use sqlx::PgPool; + +const GET_POST_BY_I64_ID: &str = include_str!("get_post_by_i64_id.sql"); +const GET_POST_BY_STR_ID: &str = include_str!("get_post_by_str_id.sql"); + +pub async fn handler( + State(db_connection): State, + Path(identifier): Path, +) -> impl IntoResponse { + let post = if let Ok(id) = identifier.parse::() { + select_post_with_i64_id(&db_connection, id).await + } else { + select_post_with_str_id(&db_connection, &identifier).await + }; + Json::from(json!({"res": "ok"})).into_response() +} + +async fn select_post_with_i64_id(db: &PgPool, id: i64) { + todo!() +} + +async fn select_post_with_str_id(db: &PgPool, id: &str) { + todo!() +} diff --git a/backend/server/src/modules/blog/api/mod.rs b/backend/server/src/modules/blog/api/mod.rs index 5e23c3d..3092117 100644 --- a/backend/server/src/modules/blog/api/mod.rs +++ b/backend/server/src/modules/blog/api/mod.rs @@ -1,3 +1,3 @@ pub mod get_page_count; pub mod get_post; -pub mod get_post_list; +// pub mod get_post_list; diff --git a/backend/server/src/modules/blog/cron/mod.rs b/backend/server/src/modules/blog/cron/mod.rs index be1305e..f5d8ad7 100644 --- a/backend/server/src/modules/blog/cron/mod.rs +++ b/backend/server/src/modules/blog/cron/mod.rs @@ -1 +1 @@ -pub mod check_update; +// pub mod check_update; diff --git a/backend/server/src/modules/blog/mod.rs b/backend/server/src/modules/blog/mod.rs index 7832bf6..9976b25 100644 --- a/backend/server/src/modules/blog/mod.rs +++ b/backend/server/src/modules/blog/mod.rs @@ -5,13 +5,14 @@ use crate::{ modules::{ blog::{ api::{ - get_page_count::get_page_count, get_post::get_post, get_post_list::get_post_list, + get_page_count, + get_post, + // get_post_list::get_post_list, }, - cron::check_update, + // cron::check_update, }, Module, }, - scheduler::tasks::basic::BasicTask, scheduler::tasks::CronTask, }; @@ -27,11 +28,12 @@ pub struct Blog { impl Module for Blog { fn get_server_router(&self) -> Router { let db_handler = self.db_handler.clone(); - // todo: remove new in get func? + // todo: move resource init to new func + // todo: remove debug comment Router::new() - .route("/get_post_list", get(get_post_list)) - .route("/get_page_count", get(get_page_count)) - .route("/get_post/:post_id", get(get_post)) + // .route("/get_post_list", get(get_post_list)) + .route("/get_page_count", get(get_page_count::handler)) + .route("/get_post/{identifier}", get(get_post::handler)) .with_state(db_handler) } @@ -40,11 +42,11 @@ impl Module for Blog { } fn get_cron_tasks(&self) -> Vec> { - let db_handler = self.db_handler.clone(); + // let db_handler = self.db_handler.clone(); vec![ - BasicTask::new(move || check_update::task(&db_handler), "0/15 * * * * *") - .unwrap() - .to_task(), + // BasicTask::new(move || check_update::task(&db_handler), "0/15 * * * * *") + // .unwrap() + // .to_task(), ] } } diff --git a/backend/server/src/modules/blog/schema.sql b/backend/server/src/modules/blog/schema.sql new file mode 100644 index 0000000..d6cd75d --- /dev/null +++ b/backend/server/src/modules/blog/schema.sql @@ -0,0 +1,41 @@ +CREATE TABLE tags +( + id SERIAL PRIMARY KEY, + name VARCHAR(20) UNIQUE NOT NULL, + description TEXT +); + +CREATE TABLE categories +( + id SERIAL PRIMARY KEY, + name VARCHAR(20) UNIQUE NOT NULL, + description TEXT +); + +CREATE TABLE posts +( + id SERIAL PRIMARY KEY, + identifier VARCHAR(50) UNIQUE NOT NULL, + title VARCHAR(255) NOT NULL, + subtitle VARCHAR(255) NOT NULL, + published_date DATE NOT NULL, + last_update DATE, + content TEXT NOT NULL, + + category SERIAL REFERENCES categories (id) NOT NULL +); + +CREATE TABLE post_tag +( + post SERIAL REFERENCES posts (id), + tag SERIAL REFERENCES tags (id) +); + +CREATE TABLE metadata +( + pid SERIAL REFERENCES posts (id) NOT NULL, + meta_key VARCHAR(50) NOT NULL, + meta_value TEXT NOT NULL, + + CONSTRAINT meta_pk PRIMARY KEY (pid, meta_key) +); diff --git a/backend/server/src/utils/git.rs b/backend/server/src/utils/git.rs index 6743058..cf906e6 100644 --- a/backend/server/src/utils/git.rs +++ b/backend/server/src/utils/git.rs @@ -16,6 +16,7 @@ pub struct FileDelta { pub status: Delta, } +#[allow(dead_code)] fn do_fetch<'a>( repo: &'a Repository, refs: &[&str], @@ -23,8 +24,6 @@ fn do_fetch<'a>( ) -> Result, git2::Error> { let mut fetch_option = FetchOptions::new(); - // Always fetch all tags. - // Perform a download and also update tips fetch_option.download_tags(AutotagOption::All); remote.fetch(refs, Some(&mut fetch_option), None)?; @@ -32,6 +31,7 @@ fn do_fetch<'a>( repo.reference_to_annotated_commit(&fetch_head) } +#[allow(dead_code)] fn fast_forward( repo: &Repository, lb: &mut Reference, @@ -45,16 +45,11 @@ fn fast_forward( // println!("{}", msg); lb.set_target(rc.id(), &msg)?; repo.set_head(&name)?; - repo.checkout_head(Some( - build::CheckoutBuilder::default() - // For some reason, the force is required to make the working directory actually get updated - // I suspect we should be adding some logic to handle dirty working directory states, - // but this is just an example so maybe not. - .force(), - ))?; + repo.checkout_head(Some(build::CheckoutBuilder::default().force()))?; Ok(()) } +#[allow(dead_code)] fn normal_merge( repo: &Repository, local: &AnnotatedCommit, @@ -73,13 +68,12 @@ fn normal_merge( return Ok(()); } let result_tree = repo.find_tree(idx.write_tree_to(repo)?)?; - // now create the merge commit + let msg = format!("merge({}) -> {}", remote.id(), local.id()); let sig = repo.signature()?; let local_commit = repo.find_commit(local.id())?; let remote_commit = repo.find_commit(remote.id())?; - // Do our merge commit and set the current branch head to that commit. let _merge_commit = repo.commit( Some("HEAD"), &sig, @@ -88,34 +82,26 @@ fn normal_merge( &result_tree, &[&local_commit, &remote_commit], )?; - // Set working tree to match head. repo.checkout_head(None)?; Ok(()) } +#[allow(dead_code)] fn do_merge<'a>( repo: &'a Repository, remote_branch: &str, fetch_commit: AnnotatedCommit<'a>, ) -> Result, git2::Error> { - // 1. do a merge analysis let analysis = repo.merge_analysis(&[&fetch_commit])?; - let head_commit = repo.reference_to_annotated_commit(&repo.head()?)?; - // 2. Do the appropriate merge if analysis.0.is_fast_forward() { - // println!("Doing a fast-forward"); - // do a fast-forward let ref_name = format!("refs/heads/{}", remote_branch); match repo.find_reference(&ref_name) { Ok(mut r) => { fast_forward(repo, &mut r, &fetch_commit)?; } Err(_) => { - // The branch doesn't exist, so set the reference to the - // commit directly. Usually this is because you are pulling - // into an empty repository. repo.reference( &ref_name, fetch_commit.id(), @@ -132,17 +118,12 @@ fn do_merge<'a>( } }; } else if analysis.0.is_normal() { - // do a normal merge normal_merge(repo, &head_commit, &fetch_commit)?; } - // else { - // // already up-to-date - // println!("Nothing to do..."); - // } - calculate_diff(repo, &head_commit, &fetch_commit) } +#[allow(dead_code)] fn calculate_diff( repo: &Repository, local: &AnnotatedCommit, @@ -156,23 +137,12 @@ fn calculate_diff( if let Err(e) = diff.foreach( &mut |d, _| { - // let delta = d.status(); - // - // let n_path = d.new_file().path(); - // let o_path = d.old_file().path(); - // - // if let Some(path) = n_path { - // updated_files.insert(path.to_owned()); - // } - // if let Some(path) = o_path { - // updated_files.insert(path.to_owned()); - // } updated_files.push(FileDelta { old_path: d.old_file().path().map(PathBuf::from), new_path: d.new_file().path().map(PathBuf::from), status: d.status(), }); - true // Continue + true }, None, None, @@ -184,6 +154,7 @@ fn calculate_diff( Ok(updated_files.into_iter().collect()) } +#[allow(dead_code)] pub fn sync( remote_name: &str, remote_branch: &str, diff --git a/loadbalancer/.gitignore b/gateway/.gitignore similarity index 100% rename from loadbalancer/.gitignore rename to gateway/.gitignore diff --git a/loadbalancer/Cargo.toml b/gateway/Cargo.toml similarity index 73% rename from loadbalancer/Cargo.toml rename to gateway/Cargo.toml index bf98b23..3417b86 100644 --- a/loadbalancer/Cargo.toml +++ b/gateway/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "loadbalancer" +name = "gateway" version = "0.1.0" edition = "2021" diff --git a/loadbalancer/src/main.rs b/gateway/src/main.rs similarity index 100% rename from loadbalancer/src/main.rs rename to gateway/src/main.rs