feat: warn or exit on config file parse errors

The relay will now fail to start if an invalid config file is
explicitly provided.  If the file was read implicitly from the current
directory, a warning will be provided, but the relay will still startup.
This commit is contained in:
Greg Heartsfield 2023-07-29 08:30:10 -05:00
parent edf7af1573
commit eab522dc39
3 changed files with 39 additions and 36 deletions

View File

@ -20,7 +20,7 @@ pub fn main() -> Result<()> {
let _trace_sub = tracing_subscriber::fmt::try_init(); let _trace_sub = tracing_subscriber::fmt::try_init();
println!("Nostr-rs-relay Bulk Loader"); println!("Nostr-rs-relay Bulk Loader");
// check for a database file, or create one. // check for a database file, or create one.
let settings = config::Settings::new(&None); let settings = config::Settings::new(&None)?;
if !Path::new(&settings.database.data_directory).is_dir() { if !Path::new(&settings.database.data_directory).is_dir() {
info!("Database directory does not exist"); info!("Database directory does not exist");
return Err(Error::DatabaseDirError); return Err(Error::DatabaseDirError);

View File

@ -1,10 +1,8 @@
//! Configuration file and settings management //! Configuration file and settings management
use crate::payment::Processor;
use config::{Config, ConfigError, File}; use config::{Config, ConfigError, File};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
use tracing::warn;
use crate::payment::Processor;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[allow(unused)] #[allow(unused)]
@ -193,18 +191,24 @@ pub struct Settings {
} }
impl Settings { impl Settings {
#[must_use] pub fn new(config_file_name: &Option<String>) -> Result<Self, ConfigError> {
pub fn new(config_file_name: &Option<String>) -> Self {
let default_settings = Self::default(); let default_settings = Self::default();
// attempt to construct settings with file // attempt to construct settings with file
let from_file = Self::new_from_default(&default_settings, config_file_name); let from_file = Self::new_from_default(&default_settings, config_file_name);
match from_file { match from_file {
Ok(f) => f,
Err(e) => { Err(e) => {
warn!("Error reading config file ({:?})", e); // pass up the parse error if the config file was specified,
default_settings // otherwise use the default config (with a warning).
if config_file_name.is_some() {
Err(e)
} else {
eprintln!("Error reading config file ({:?})", e);
eprintln!("WARNING: Default configuration settings will be used");
Ok(default_settings)
} }
} }
ok => ok,
}
} }
fn new_from_default( fn new_from_default(

View File

@ -4,12 +4,12 @@ use console_subscriber::ConsoleLayer;
use nostr_rs_relay::cli::CLIArgs; use nostr_rs_relay::cli::CLIArgs;
use nostr_rs_relay::config; use nostr_rs_relay::config;
use nostr_rs_relay::server::start_server; use nostr_rs_relay::server::start_server;
use std::fs;
use std::path::Path;
use std::process;
use std::sync::mpsc as syncmpsc; use std::sync::mpsc as syncmpsc;
use std::sync::mpsc::{Receiver as MpscReceiver, Sender as MpscSender}; use std::sync::mpsc::{Receiver as MpscReceiver, Sender as MpscSender};
use std::thread; use std::thread;
use std::path::Path;
use std::fs;
use std::process;
#[cfg(not(target_env = "msvc"))] #[cfg(not(target_env = "msvc"))]
use tikv_jemallocator::Jemalloc; use tikv_jemallocator::Jemalloc;
use tracing::info; use tracing::info;
@ -27,36 +27,35 @@ fn main() {
// get config file name from args // get config file name from args
let config_file_arg = args.config; let config_file_arg = args.config;
// Quits if config file path is unreadable or does not exist // Ensure the config file is readable if it was explicitly set
let config_file_path = config_file_arg.as_ref().map(|x| &**x).unwrap(); if let Some(config_path) = config_file_arg.as_ref() {
let path = Path::new(&config_file_path); let path = Path::new(&config_path);
if !path.exists() { if !path.exists() {
eprintln!("Config file not found: {}", &config_file_path); eprintln!("Config file not found: {}", &config_path);
process::exit(1); process::exit(1);
} }
if !path.is_file() { if !path.is_file() {
eprintln!("Invalid config file path: {}", &config_file_path); eprintln!("Invalid config file path: {}", &config_path);
process::exit(1); process::exit(1);
} }
if let Err(err) = fs::metadata(path) {
if let Err(err) = fs::metadata(&path) {
eprintln!("Error while accessing file metadata: {}", err); eprintln!("Error while accessing file metadata: {}", err);
process::exit(1); process::exit(1);
} }
if let Err(err) = fs::File::open(path) {
if let Err(err) = fs::File::open(&path) {
eprintln!("Config file is not readable: {}", err); eprintln!("Config file is not readable: {}", err);
process::exit(1); process::exit(1);
} }
}
let mut _log_guard: Option<WorkerGuard> = None; let mut _log_guard: Option<WorkerGuard> = None;
// configure settings from the config file (defaults to config.toml) // configure settings from the config file (defaults to config.toml)
// replace default settings with those read from the config file // replace default settings with those read from the config file
let mut settings = config::Settings::new(&config_file_arg); let mut settings = config::Settings::new(&config_file_arg).unwrap_or_else(|e| {
eprintln!("Error reading config file ({:?})", e);
process::exit(1);
});
// setup tracing // setup tracing
if settings.diagnostics.tracing { if settings.diagnostics.tracing {