added config.toml support for flexible server configuration, integrated toml crate for parsing, refactored configuration management to use AppSettings, and updated database initialization logic

This commit is contained in:
2025-08-05 11:24:59 +02:00
parent a30f8467bc
commit f22259b863
6 changed files with 132 additions and 30 deletions

View File

@@ -1,33 +1,67 @@
use serde::Deserialize;
use std::env;
use std::path::PathBuf;
use toml::Value;
use tracing::{error, info};
#[derive(Debug, Clone)]
pub struct Config {
#[derive(Deserialize, Debug)]
pub struct AppSettings {
pub config_path: String,
pub db_path: String,
pub migration_path: String,
pub config: Config,
}
#[derive(Deserialize, Debug)]
pub struct Config {
pub server: Server,
}
#[derive(Deserialize, Debug)]
pub struct Server {
pub host: String,
pub port: u16,
}
impl Config {
pub fn from_env() -> Self {
#[derive(Deserialize, Debug)]
struct ConfigFile {
server: Server,
}
impl AppSettings {
pub fn get_app_settings() -> Self {
let config_file = Self::load_config_file().unwrap_or_else(|| {
info!("Using default config values");
ConfigFile {
server: Server {
host: "127.0.0.1".to_string(),
port: 1337,
},
}
});
Self {
config_path: Self::get_config_path(),
db_path: Self::get_db_path(),
migration_path: std::env::var("MIGRATION_PATH")
.unwrap_or_else(|_| "./migrations".to_string()),
host: env::var("HOST").unwrap_or_else(|_| "127.0.0.1".to_string()),
port: env::var("PORT")
.unwrap_or_else(|_| "1337".to_string())
.parse()
.expect("PORT must be a number"),
migration_path: String::from("./migrations"),
config: Config {
server: config_file.server,
},
}
}
fn get_db_path() -> String {
if let Ok(db_path) = env::var("DATABASE_PATH") {
return db_path;
}
fn load_config_file() -> Option<ConfigFile> {
let config_path = Self::get_config_path();
let contents = std::fs::read_to_string(&config_path)
.map_err(|e| error!("Failed to read config file: {}", e))
.ok()?;
toml::from_str(&contents)
.map_err(|e| error!("Failed to parse TOML: {}", e))
.ok()
}
fn get_db_path() -> String {
if cfg!(debug_assertions) {
// Development: Use backend-rust directory
// TODO: Change later
@@ -40,6 +74,19 @@ impl Config {
}
}
fn get_config_path() -> String {
if cfg!(debug_assertions) {
// Development: Use backend-rust directory
// TODO: Change later
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push("config.toml");
path.to_str().unwrap().to_string()
} else {
// Production: Use standard Linux applications data directory
"$HOME/owly-news-summariser/config.toml".to_string()
}
}
pub fn database_url(&self) -> String {
format!("sqlite:{}", self.db_path)
}

View File

@@ -1,17 +1,17 @@
use crate::config::Config;
use crate::config::{AppSettings};
use anyhow::Result;
use sqlx::migrate::Migrator;
use sqlx::sqlite::{SqliteConnectOptions, SqliteConnection};
use sqlx::sqlite::{SqliteConnectOptions};
use sqlx::{Pool, Sqlite, SqlitePool};
use std::str::FromStr;
use tracing::info;
pub const MIGRATOR: Migrator = sqlx::migrate!("./migrations");
pub async fn initialize_db(config: &Config) -> Result<Pool<Sqlite>> {
config.ensure_db_directory()?;
pub async fn initialize_db(app_settings: &AppSettings) -> Result<Pool<Sqlite>> {
app_settings.ensure_db_directory()?;
let options = SqliteConnectOptions::from_str(&config.database_url())?
let options = SqliteConnectOptions::from_str(&app_settings.database_url())?
.create_if_missing(true)
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
.foreign_keys(true);

View File

@@ -4,16 +4,12 @@ mod db;
mod models;
mod services;
use crate::config::Config;
use crate::config::{AppSettings};
use anyhow::Result;
use axum::Router;
use axum::routing::get;
use sqlx::sqlite::SqliteConnectOptions;
use std::str::FromStr;
use tokio::signal;
use tokio::signal::ctrl_c;
use tokio::signal::unix::signal;
use tracing::{error, info};
use tracing::{info};
use tracing_subscriber;
#[tokio::main]
@@ -23,15 +19,15 @@ async fn main() -> Result<()> {
.compact()
.init();
let config = Config::from_env();
let app_settings = AppSettings::get_app_settings();
let pool = db::initialize_db(&config).await?;
let pool = db::initialize_db(&app_settings).await?;
let app = create_app(pool);
let listener =
tokio::net::TcpListener::bind(format!("{}:{}", config.host, config.port)).await?;
info!("Server starting on {}:{}", config.host, config.port);
tokio::net::TcpListener::bind(format!("{}:{}", app_settings.config.server.host, app_settings.config.server.port)).await?;
info!("Server starting on {}:{}", app_settings.config.server.host, app_settings.config.server.port);
axum::serve(listener, app)
.with_graceful_shutdown(shutdown_signal())