ref(global) move modules, extract constants

This commit is contained in:
lumither committed 2024-11-20 00:57:54 -08:00
1 parent c7e3b12856
commit e26003f430
10 files changed
+216 -152

No files matched your search

@@ -1,6 +1,7 @@
use dirs::home_dir;
use std::env; use std::env;
use dirs::home_dir;
pub fn task() { pub fn task() {
// get dir // get dir
let git_work_dir_path = &env::var("GIT_WORK_DIR").unwrap_or_else(|e| { let git_work_dir_path = &env::var("GIT_WORK_DIR").unwrap_or_else(|e| {
-23
View File
@@ -1,23 +0,0 @@
use crate::logger;
use std::{env, panic};
use tracing_appender::non_blocking::WorkerGuard;
pub fn logger_init() -> (WorkerGuard, WorkerGuard) {
logger::init()
}
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")
}
}
+38
View File
@@ -0,0 +1,38 @@
use std::env;
use std::error::Error;
use std::str::FromStr;
use 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().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}")
})
}
@@ -2,6 +2,7 @@ use std::path::Path;
use std::{env, io}; use std::{env, io};
use chrono::Local; use chrono::Local;
use constants::config::general::{default_value, var_name};
use dirs::home_dir; use dirs::home_dir;
use tracing::info; use tracing::info;
use tracing_appender::{non_blocking, non_blocking::WorkerGuard, rolling}; use tracing_appender::{non_blocking, non_blocking::WorkerGuard, rolling};
@@ -25,33 +26,26 @@ impl FormatTime for LocalTimer {
type _LogWriter = dyn for<'writer> MakeWriter<'writer, Writer = dyn io::Write + 'static> + 'static; type _LogWriter = dyn for<'writer> MakeWriter<'writer, Writer = dyn io::Write + 'static> + 'static;
pub fn init() -> (WorkerGuard, WorkerGuard) { pub fn init() -> (WorkerGuard, WorkerGuard) {
let log_path = &env::var("LOG_ROOT_DIR").unwrap_or_else(|e| { let log_path = match env::var(var_name::LOG_DIR) {
if let Ok(default_log_path) = env::var("WORK_DIR") { Ok(path) => Path::new(&path).to_path_buf(),
if default_log_path.starts_with('~') { Err(_) => {
let home_path = home_dir() let path = if let Ok(default_log_path) = env::var(var_name::WORK_DIR) {
.expect("[fatal] unable to locate home dir with parsing env `WORK_DIR`, try to use absolute path instead"); expand_home_path(default_log_path)
home_path
.join(default_log_path.strip_prefix("~/").unwrap())
.into_os_string()
.into_string()
.expect("[fatal] failed to parse env `WORK_DIR`, try to use absolute path instead")
} else { } else {
default_log_path let fallback_path = expand_home_path(default_value::WORK_DIR.to_string());
} println!(
} else { "[warn] unset env var `{}` and `{}`, trying to log on fallback path: {}/log",
panic!("[fatal] failed to parse env `LOG_ROOT_DIR`: {}", e); var_name::LOG_DIR,
var_name::WORK_DIR,
fallback_path
);
fallback_path
};
Path::new(&path).join("log")
} }
}); };
let log_path = Path::new(log_path)
.join("log")
.join("backend")
.into_os_string()
.into_string()
.unwrap_or_else(|e| panic!("[fatal] failed to parse {:?}", e));
let (info_log_writer, info_guard) = non_blocking(rolling::never(&log_path, "info.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 (err_log_writer, error_guard) = non_blocking(rolling::never(&log_path, "error.log"));
let info_format = tracing_subscriber::fmt::format() let info_format = tracing_subscriber::fmt::format()
@@ -70,9 +64,6 @@ pub fn init() -> (WorkerGuard, WorkerGuard) {
.with_source_location(true) .with_source_location(true)
.with_timer(LocalTimer); .with_timer(LocalTimer);
// let default_filter = tracing_subscriber::filter::EnvFilter::try_from_default_env()
// .unwrap_or_else(|_| "tower_http=debug,axum::rejection=trace".into());
let subscribers = Registry::default() let subscribers = Registry::default()
.with( .with(
fmt::Layer::default() fmt::Layer::default()
@@ -95,8 +86,21 @@ pub fn init() -> (WorkerGuard, WorkerGuard) {
tracing::subscriber::set_global_default(subscribers) tracing::subscriber::set_global_default(subscribers)
.expect("[fatal] failed to setup logging system"); .expect("[fatal] failed to setup logging system");
info!("module started: logger"); info!("logging to dir: {}", log_path.to_str().unwrap());
info!("logging to dir: {}", log_path);
(info_guard, error_guard) (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
}
}
+45
View File
@@ -0,0 +1,45 @@
mod database;
pub mod logger;
pub mod server;
use macros::panic_with_log;
use std::{env, panic};
use tracing::{info, Level};
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() {
let db_pool = match database::init().await {
Ok(pool) => {
info!("database connection pool initialized");
pool
}
Err(e) => {
panic_with_log!(
Level::ERROR,
"database connection pool failed to initialize: {}",
e
);
}
};
match server::start(db_pool).await {
Ok(_) => {}
Err(e) => {
panic_with_log!(Level::ERROR, "server panicked: {}", e)
}
}
}
+52
View File
@@ -0,0 +1,52 @@
use std::env;
use std::error::Error;
use std::num::ParseIntError;
use std::process::exit;
use crate::blog;
use axum::Router;
use constants::config::server::{default_value, var_name};
use macros::panic_with_log;
use sqlx::{Pool, Postgres};
use tracing::{error, info, warn, Level};
pub async fn start(db_pool: Pool<Postgres>) -> Result<(), Box<dyn Error>> {
let app = Router::new()
.nest("/blog", blog::get_router())
.with_state(db_pool);
let port: u32 = match env::var(var_name::PORT) {
Ok(value) => value.parse().unwrap_or_else(|e: ParseIntError| {
warn!(
"failed to parse `{}`, using default port: {}",
var_name::PORT,
e.to_string()
);
default_value::PORT
}),
Err(_) => default_value::PORT,
};
let listener =
match tokio::net::TcpListener::bind(format!("{}:{}", default_value::HOST, port)).await {
Ok(listener) => {
info!("server started on {}:{}", default_value::HOST, port);
listener
}
Err(e) => {
panic_with_log!(
Level::ERROR,
"failed to start server on {}:{}: {}",
default_value::HOST,
port,
e.to_string()
);
}
};
axum::serve(listener, app).await.unwrap_or_else(|e| {
error!("failed to start axum: {}", e.to_string());
exit(1);
});
Ok(())
}
+3 -12
View File
@@ -1,21 +1,12 @@
use macros::panic_with_log;
use tracing::Level;
mod blog; mod blog;
mod init; mod init;
mod logger;
mod scheduler; mod scheduler;
mod server;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
init::load_env(); init::load_env();
let _guards = init::logger_init();
match server::start().await { let _guards = init::logger::init();
Ok(_) => {}
Err(e) => { init::start().await;
panic_with_log!(Level::ERROR, "failed to start server: {}", e);
}
};
} }
-88
View File
@@ -1,88 +0,0 @@
use std::env;
use std::error::Error;
use std::num::ParseIntError;
use std::process::exit;
use std::str::FromStr;
use crate::blog;
use axum::Router;
use macros::panic_with_log;
use sqlx::{
postgres::{PgConnectOptions, PgPoolOptions},
ConnectOptions,
};
use tracing::{error, info, warn, Level};
pub async fn start() -> Result<(), Box<dyn Error>> {
let port: u32 = match env::var("BACKEND_PORT") {
Ok(value) => value.parse().unwrap_or_else(|e: ParseIntError| {
warn!("failed to parse BACKEND_PORT: {}", e.to_string());
3001
}),
Err(_) => 3001,
};
let db_connect_option = PgConnectOptions::from_str(&parse_db_uri())
.unwrap()
.disable_statement_logging();
let db_pool = match PgPoolOptions::new().connect_with(db_connect_option).await {
Ok(pool) => {
info!("database connected");
pool
}
Err(e) => {
error!("failed to load database: {}", e.to_string());
exit(1);
}
};
// cron task
// let scheduler = Scheduler::new();
// let test_str = "hello world".to_string();
// scheduler.insert(
// BasicTask::new(
// move || blog::cron::check_update::task(test_str.clone()),
// "* * * * * *",
// )?
// .to_task(),
// )?;
// http server
let app = Router::new()
.nest("/blog", blog::get_router())
.with_state(db_pool);
let listener = match tokio::net::TcpListener::bind(format!("0.0.0.0:{}", port)).await {
Ok(listener) => {
info!("server started on 0.0.0.0:{}", port);
listener
}
Err(e) => {
panic_with_log!(
Level::ERROR,
"failed to start server on 0.0.0.0:{}: {}",
port,
e.to_string()
);
}
};
axum::serve(listener, app).await.unwrap_or_else(|e| {
error!("failed to start axum: {}", e.to_string());
exit(1);
});
Ok(())
}
fn parse_db_uri() -> String {
let postgres_user = env::var("POSTGRES_USER").unwrap_or("".to_string());
let postgres_password = env::var("POSTGRES_PASSWORD").unwrap_or("".to_string());
let db_host = env::var("DB_HOST").unwrap_or("localhost".to_string());
let db_port = env::var("DB_PORT")
.unwrap_or("5432".to_string())
.to_string();
let postgres_db = env::var("POSTGRES_DB").unwrap_or("nocturne".to_string());
format!("postgresql://{postgres_user}:{postgres_password}@{db_host}:{db_port}/{postgres_db}")
}
+43
View File
@@ -0,0 +1,43 @@
// Database related
pub mod database {
pub mod var_name {
pub const URI: &str = "DATABASE_URL";
pub const USERNAME: &str = "POSTGRES_USER";
pub const PASSWORD: &str = "POSTGRES_PASSWORD";
pub const HOST: &str = "POSTGRES_HOST";
pub const PORT: &str = "POSTGRES_PORT";
pub const DBNAME: &str = "POSTGRES_DB";
}
pub mod default_value {
pub const USERNAME: &str = "";
pub const PASSWORD: &str = "";
pub const HOST: &str = "localhost";
pub const PORT: &str = "5432";
pub const DBNAME: &str = "nocturne";
pub const DATABASE_TYPE: &str = "postgresql";
}
}
pub mod server {
pub mod var_name {
pub const PORT: &str = "BACKEND_PORT";
pub const HOST: &str = "BACKEND_HOST";
}
pub mod default_value {
pub const PORT: u32 = 3001;
pub const HOST: &str = "0.0.0.0";
}
}
pub mod general {
pub mod var_name {
pub const LOG_DIR: &str = "LOG_DIR";
pub const WORK_DIR: &str = "WORK_DIR";
}
pub mod default_value {
pub const WORK_DIR: &str = "~/.nocturne";
}
}
+1
View File
@@ -1,2 +1,3 @@
pub mod blog; pub mod blog;
pub mod config;
pub mod time; pub mod time;