mirror of
https://github.com/Lumither/nocturne.git
synced 2026-10-17 10:26:21 +00:00
ref(global) move modules, extract constants
This commit is contained in:
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| {
|
||||||
|
|||||||
@@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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!(
|
||||||
|
"[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")
|
||||||
}
|
}
|
||||||
} else {
|
};
|
||||||
panic!("[fatal] failed to parse env `LOG_ROOT_DIR`: {}", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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(())
|
||||||
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
@@ -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}")
|
|
||||||
}
|
|
||||||
@@ -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,2 +1,3 @@
|
|||||||
pub mod blog;
|
pub mod blog;
|
||||||
|
pub mod config;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
Reference in new issue
Block a user