mirror of
https://github.com/Lumither/nocturne.git
synced 2026-10-17 18:36:21 +00:00
feat(backend) update (unfinished)
This commit is contained in:
26 files changed
+1607
-14
No files matched your search
@@ -0,0 +1,42 @@
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::constants::config::database::{default_value, var_name};
|
||||
|
||||
use sqlx::postgres::{PgConnectOptions, PgPoolOptions};
|
||||
use sqlx::{ConnectOptions, Pool, Postgres};
|
||||
use tracing::info;
|
||||
|
||||
pub async fn init() -> Result<Pool<Postgres>, Box<dyn Error>> {
|
||||
let db_connect_option = PgConnectOptions::from_str(&parse_db_uri())
|
||||
.unwrap()
|
||||
.disable_statement_logging();
|
||||
Ok(PgPoolOptions::new()
|
||||
.max_connections(1) // todo: temporary solution, to be fixed
|
||||
.connect_with(db_connect_option)
|
||||
.await?)
|
||||
}
|
||||
|
||||
fn parse_db_uri() -> String {
|
||||
env::var(var_name::URI).unwrap_or_else(|_| {
|
||||
info!(
|
||||
"`{}` env var is not set, \
|
||||
using `{}`, `{}`, `{}`, `{}` and `{}`",
|
||||
var_name::URI,
|
||||
var_name::USERNAME,
|
||||
var_name::PASSWORD,
|
||||
var_name::HOST,
|
||||
var_name::PORT,
|
||||
var_name::DBNAME
|
||||
);
|
||||
let postgres_user = env::var(var_name::USERNAME).unwrap_or(default_value::USERNAME.into());
|
||||
let postgres_password =
|
||||
env::var(var_name::PASSWORD).unwrap_or(default_value::PASSWORD.into());
|
||||
let db_host = env::var(var_name::HOST).unwrap_or(default_value::HOST.into());
|
||||
let db_port = env::var(var_name::PORT).unwrap_or(default_value::PORT.into());
|
||||
let postgres_db = env::var(var_name::DBNAME).unwrap_or(default_value::DBNAME.into());
|
||||
let db_type = default_value::DATABASE_TYPE;
|
||||
format!("{db_type}://{postgres_user}:{postgres_password}@{db_host}:{db_port}/{postgres_db}")
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
use std::path::Path;
|
||||
use std::{env, io};
|
||||
|
||||
use crate::constants::config::general::{default_value, var_name};
|
||||
|
||||
use chrono::Local;
|
||||
use dirs::home_dir;
|
||||
use tracing::info;
|
||||
use tracing_appender::{non_blocking, non_blocking::WorkerGuard, rolling};
|
||||
use tracing_subscriber::{
|
||||
filter::LevelFilter, fmt, fmt::format::Writer, fmt::time::FormatTime, fmt::MakeWriter,
|
||||
layer::SubscriberExt, Layer, Registry,
|
||||
};
|
||||
|
||||
struct LocalTimer;
|
||||
|
||||
impl FormatTime for LocalTimer {
|
||||
fn format_time(&self, w: &mut Writer<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
w,
|
||||
"{}",
|
||||
Local::now().format(crate::constants::time::DEFAULT_TIME_FORMAT)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type _LogWriter = dyn for<'writer> MakeWriter<'writer, Writer = dyn io::Write + 'static> + 'static;
|
||||
|
||||
pub fn init() -> (WorkerGuard, WorkerGuard) {
|
||||
let log_path = match env::var(var_name::LOG_DIR) {
|
||||
Ok(path) => Path::new(&path).to_path_buf(),
|
||||
Err(_) => {
|
||||
let path = if let Ok(default_log_path) = env::var(var_name::WORK_DIR) {
|
||||
expand_home_path(default_log_path)
|
||||
} else {
|
||||
let fallback_path = expand_home_path(default_value::WORK_DIR.to_string());
|
||||
println!(
|
||||
"[warn] unset env var `{}` and `{}`, trying to log on fallback path: {}/log",
|
||||
var_name::LOG_DIR,
|
||||
var_name::WORK_DIR,
|
||||
fallback_path
|
||||
);
|
||||
fallback_path
|
||||
};
|
||||
Path::new(&path).join("log")
|
||||
}
|
||||
};
|
||||
|
||||
let (info_log_writer, info_guard) = non_blocking(rolling::never(&log_path, "info.log"));
|
||||
let (err_log_writer, error_guard) = non_blocking(rolling::never(&log_path, "error.log"));
|
||||
|
||||
let info_format = tracing_subscriber::fmt::format()
|
||||
.with_level(true)
|
||||
.with_target(true)
|
||||
.with_source_location(true)
|
||||
.with_ansi(false);
|
||||
let err_format = tracing_subscriber::fmt::format()
|
||||
.with_level(true)
|
||||
.with_target(true)
|
||||
.with_source_location(true)
|
||||
.with_ansi(false);
|
||||
let stdout_format = tracing_subscriber::fmt::format()
|
||||
.with_level(true)
|
||||
.with_target(true)
|
||||
.with_source_location(true)
|
||||
.with_timer(LocalTimer);
|
||||
|
||||
let subscribers = Registry::default()
|
||||
.with(
|
||||
fmt::Layer::default()
|
||||
.with_writer(info_log_writer)
|
||||
.event_format(info_format),
|
||||
)
|
||||
.with(
|
||||
fmt::Layer::default()
|
||||
.with_writer(err_log_writer)
|
||||
.event_format(err_format)
|
||||
.with_filter(LevelFilter::ERROR),
|
||||
)
|
||||
.with(
|
||||
fmt::Layer::default()
|
||||
.with_writer(io::stdout)
|
||||
.with_ansi(true)
|
||||
.event_format(stdout_format),
|
||||
);
|
||||
|
||||
tracing::subscriber::set_global_default(subscribers)
|
||||
.expect("[fatal] failed to setup logging system");
|
||||
|
||||
info!("logging to dir: {}", log_path.to_str().unwrap());
|
||||
|
||||
(info_guard, error_guard)
|
||||
}
|
||||
|
||||
fn expand_home_path(path: String) -> String {
|
||||
if path.starts_with('~') {
|
||||
let home_path = home_dir()
|
||||
.unwrap_or_else(|| panic!("[fatal] unable to locate home dir when parsing env `{}`, try to use absolute path instead", var_name::WORK_DIR));
|
||||
home_path
|
||||
.join(path.strip_prefix("~/").unwrap())
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.unwrap()
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
use git2::opts::{set_server_connect_timeout_in_milliseconds, set_server_timeout_in_milliseconds};
|
||||
use tracing::warn;
|
||||
|
||||
pub fn init() {
|
||||
// git2 option
|
||||
unsafe {
|
||||
if let Err(e) = set_server_connect_timeout_in_milliseconds(10_000) {
|
||||
warn!("failed to set git2 server connect timeout: {}", e);
|
||||
}
|
||||
if let Err(e) = set_server_timeout_in_milliseconds(60_000) {
|
||||
warn!("failed to set git2 server timeout: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
mod database;
|
||||
pub mod logger;
|
||||
mod misc;
|
||||
mod schema;
|
||||
|
||||
use std::{env, panic};
|
||||
|
||||
use crate::modules::{blog::Blog, ModuleTree};
|
||||
use macros::error_panic;
|
||||
|
||||
use tracing::info;
|
||||
|
||||
pub fn load_env() {
|
||||
if let Some(env_file) = env::args().nth(1) {
|
||||
match dotenv::from_filename(&env_file) {
|
||||
Ok(_) => {
|
||||
println!("[info] env loaded from {}, starting up", env_file);
|
||||
}
|
||||
Err(e) => {
|
||||
panic!("[fatal] failed to read {}: {}", env_file, e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("[info] no .env file referred, starting up")
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start() {
|
||||
misc::init();
|
||||
|
||||
// connect database
|
||||
let db_pool = match database::init().await {
|
||||
Ok(pool) => {
|
||||
info!("database connection pool initialized");
|
||||
pool
|
||||
}
|
||||
Err(e) => {
|
||||
error_panic!("database connection pool failed to initialize: {}", e);
|
||||
}
|
||||
};
|
||||
|
||||
// // schema init
|
||||
// schema::init(&db_pool).await;
|
||||
|
||||
ModuleTree::new()
|
||||
.add_module(Blog {
|
||||
db_handler: db_pool,
|
||||
})
|
||||
.blocking_serve()
|
||||
.await
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
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<Postgres>) {
|
||||
// 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");
|
||||
}
|
||||
Reference in new issue
Block a user