diff --git a/bothan-api/server-cli/src/commands.rs b/bothan-api/server-cli/src/commands.rs index 01db14eb..9ab6265c 100644 --- a/bothan-api/server-cli/src/commands.rs +++ b/bothan-api/server-cli/src/commands.rs @@ -1,3 +1,2 @@ pub mod config; pub mod start; -mod utils; diff --git a/bothan-api/server-cli/src/commands/config.rs b/bothan-api/server-cli/src/commands/config.rs index ac031c2d..01819c7d 100644 --- a/bothan-api/server-cli/src/commands/config.rs +++ b/bothan-api/server-cli/src/commands/config.rs @@ -1,13 +1,12 @@ use std::fs; use std::path::PathBuf; -use anyhow::Context; -use clap::{Parser, Subcommand}; - +use crate::bothan_home_dir; +use anyhow::{anyhow, Context}; use bothan_api::config::manager::crypto_info::sources::CryptoSourceConfigs; use bothan_api::config::AppConfig; - -use crate::commands::utils::bothan_home_dir; +use clap::{Parser, Subcommand}; +use tracing::info; #[derive(Parser)] pub struct ConfigCli { @@ -22,18 +21,27 @@ enum ConfigSubCommand { /// The path to where to initialize the configuration file (defaults to ./config.toml). #[arg(short, long)] path: Option, + + /// Whether to override the existing configuration file. + #[arg(short, long = "override")] + override_: bool, }, } impl ConfigCli { pub async fn run(&self) -> anyhow::Result<()> { match &self.subcommand { - ConfigSubCommand::Init { path } => { + ConfigSubCommand::Init { path, override_ } => { let config_path = match path { Some(p) => p.clone(), None => bothan_home_dir().join("config.toml"), }; + //check if the file already exists + if config_path.exists() && !override_ { + return Err(anyhow!("Config file already exists at: {:?}", config_path)); + } + if let Some(parent) = config_path.parent() { fs::create_dir_all(parent).with_context(|| { format!("Failed to create parent directories for {:?}", path) @@ -45,8 +53,8 @@ impl ConfigCli { let config_string = toml::to_string(&app_config).with_context(|| "Failed to serialize config")?; - fs::write(config_path, config_string).with_context(|| "Failed to write config")?; - println!("Initialized default config at: {:?}", path); + fs::write(&config_path, config_string).with_context(|| "Failed to write config")?; + info!("initialized default config at: {:?}", config_path); Ok(()) } } diff --git a/bothan-api/server-cli/src/commands/start.rs b/bothan-api/server-cli/src/commands/start.rs index 1aeae883..656f461d 100644 --- a/bothan-api/server-cli/src/commands/start.rs +++ b/bothan-api/server-cli/src/commands/start.rs @@ -5,11 +5,6 @@ use std::str::FromStr; use std::sync::Arc; use anyhow::{anyhow, Context}; -use clap::Parser; -use reqwest::header::{HeaderName, HeaderValue}; -use semver::VersionReq; -use tonic::transport::Server; - use bothan_api::api::CryptoQueryServer; use bothan_api::config::ipfs::IpfsAuthentication; use bothan_api::config::manager::crypto_info::sources::CryptoSourceConfigs; @@ -25,8 +20,11 @@ use bothan_core::registry::{Registry, Valid}; use bothan_core::store::SharedStore; use bothan_core::worker::AssetWorkerBuilder; use bothan_kraken::KrakenWorkerBuilder; - -use crate::commands::utils::bothan_home_dir; +use clap::Parser; +use reqwest::header::{HeaderName, HeaderValue}; +use semver::VersionReq; +use tonic::transport::Server; +use tracing::info; #[derive(Parser)] pub struct StartCli { @@ -48,14 +46,7 @@ pub struct StartCli { } impl StartCli { - pub async fn run(&self) -> anyhow::Result<()> { - let config_path = self - .config - .clone() - .unwrap_or(bothan_home_dir().join("config.toml")); - - let app_config = AppConfig::from(config_path)?; - + pub async fn run(&self, app_config: AppConfig) -> anyhow::Result<()> { let registry = match &self.registry { Some(p) => { let file = @@ -84,16 +75,11 @@ async fn start_server( registry: Registry, reset: bool, ) -> anyhow::Result<()> { - let log_level = &app_config.log.level; - tracing_subscriber::fmt() - .with_env_filter(format!("bothan_core={log_level},bothan_api={log_level}")) - .init(); - let store = init_store(&app_config, registry, reset).await?; let ipfs_client = init_ipfs_client(&app_config).await?; let crypto_server = Arc::new(init_crypto_server(&app_config, store, ipfs_client).await?); - println!("Server started"); + info!("server started"); Server::builder() .add_service(PriceServiceServer::from_arc(crypto_server.clone())) .add_service(SignalServiceServer::from_arc(crypto_server.clone())) @@ -121,7 +107,7 @@ async fn init_store( let mut store = SharedStore::new(registry, &config.store.path) .await .with_context(|| "Failed to create store")?; - println!("Store created successfully at \"{:?}\"", &config.store.path); + info!("store created successfully at \"{:?}\"", &config.store.path); if !reset { store @@ -209,6 +195,6 @@ where .with_context(|| format!("Failed to build worker {worker_name}"))?; manager.add_worker(worker_name.to_string(), worker).await; - println!("Loaded {} worker", worker_name); + info!("loaded {} worker", worker_name); Ok(()) } diff --git a/bothan-api/server-cli/src/commands/utils.rs b/bothan-api/server-cli/src/commands/utils.rs deleted file mode 100644 index 6dc0a76b..00000000 --- a/bothan-api/server-cli/src/commands/utils.rs +++ /dev/null @@ -1,6 +0,0 @@ -use std::path::PathBuf; - -pub fn bothan_home_dir() -> PathBuf { - let home = dirs::home_dir().expect("Failed to get home directory"); - home.join(".bothan") -} diff --git a/bothan-api/server-cli/src/main.rs b/bothan-api/server-cli/src/main.rs index 1cb018fc..f7c1339c 100644 --- a/bothan-api/server-cli/src/main.rs +++ b/bothan-api/server-cli/src/main.rs @@ -1,5 +1,9 @@ +use std::path::PathBuf; + use clap::{Parser, Subcommand}; +use bothan_api::config::AppConfig; + use crate::commands::config::ConfigCli; use crate::commands::start::StartCli; @@ -10,6 +14,10 @@ mod commands; struct Cli { #[command(subcommand)] command: Option, + + // global args + #[arg(long, global = true)] + config: Option, } #[derive(Subcommand)] @@ -30,13 +38,30 @@ async fn main() { } }; + let config_path = cli + .config + .clone() + .unwrap_or(bothan_home_dir().join("config.toml")); + + let app_config = AppConfig::from(config_path).expect("Failed to load config"); + + let log_level = &app_config.log.level; + tracing_subscriber::fmt() + .with_env_filter(format!( + "bothan_core={log_level},bothan_api={log_level},bothan={log_level}" + )) + .init(); + if let Some(command) = &cli.command { - if let Err(e) = match command { + match command { Command::Config(config_cli) => config_cli.run().await, - Command::Start(start_cli) => start_cli.run().await, - } { - eprintln!("{}", e); - std::process::exit(1); + Command::Start(start_cli) => start_cli.run(app_config).await, } + .expect("Failed to run command"); } } + +pub fn bothan_home_dir() -> PathBuf { + let home = dirs::home_dir().expect("Failed to get home directory"); + home.join(".bothan") +} diff --git a/bothan-api/server/src/api/crypto.rs b/bothan-api/server/src/api/crypto.rs index 7f542c53..f4275399 100644 --- a/bothan-api/server/src/api/crypto.rs +++ b/bothan-api/server/src/api/crypto.rs @@ -72,8 +72,8 @@ impl SignalService for CryptoQueryServer { error!("invalid IPFS hash"); Err(Status::invalid_argument("Invalid IPFS hash")) } - Err(SetRegistryError::FailedToSetRegistry(_)) => { - error!("Failed to set registry"); + Err(SetRegistryError::FailedToSetRegistry(e)) => { + error!("failed to set registry: {e}"); Err(Status::internal("Failed to set registry")) } } diff --git a/bothan-api/server/src/api/utils.rs b/bothan-api/server/src/api/utils.rs index 01c95b63..cc600724 100644 --- a/bothan-api/server/src/api/utils.rs +++ b/bothan-api/server/src/api/utils.rs @@ -15,7 +15,7 @@ pub fn parse_price_state(id: String, price_state: PriceState) -> Price { match i64::try_from(mantissa_price) { Ok(p) => Price::new(id, p, Status::Available), Err(_) => { - warn!("Failed to convert {mantissa_price} to i64 for id {id}"); + warn!("failed to convert {mantissa_price} to i64 for id {id}"); Price::new(id, 0, Status::Unavailable) } } diff --git a/bothan-coinbase/src/api/websocket.rs b/bothan-coinbase/src/api/websocket.rs index fbde7f64..2941a378 100644 --- a/bothan-coinbase/src/api/websocket.rs +++ b/bothan-coinbase/src/api/websocket.rs @@ -29,7 +29,7 @@ impl CoinbaseWebSocketConnector { let status = resp.status(); if StatusCode::is_server_error(&status) || StatusCode::is_client_error(&status) { - warn!("Failed to connect with response code {}", resp.status()); + warn!("failed to connect with response code {}", resp.status()); return Err(Error::ConnectionFailure(resp.status())); } diff --git a/bothan-coinbase/src/service.rs b/bothan-coinbase/src/service.rs index 2db12fed..82bca4e1 100644 --- a/bothan-coinbase/src/service.rs +++ b/bothan-coinbase/src/service.rs @@ -78,7 +78,7 @@ impl Service for CoinbaseService { .collect(); if !sub_ids.is_empty() && self.cmd_tx.send(Command::Subscribe(sub_ids)).await.is_err() { - warn!("Failed to send subscribe command"); + warn!("failed to send subscribe command"); } result @@ -143,7 +143,7 @@ async fn process_command( .await .is_err() { - warn!("Failed to subscribe to ids: {:?}", ids); + warn!("failed to subscribe to ids: {:?}", ids); } } } @@ -177,7 +177,7 @@ async fn handle_reconnect( }; if command_tx.send(cmd).await.is_err() { - error!("Failed to send subscribe command"); + error!("failed to send subscribe command"); }; } diff --git a/bothan-core/src/store.rs b/bothan-core/src/store.rs index 63105043..f5ee7c5f 100644 --- a/bothan-core/src/store.rs +++ b/bothan-core/src/store.rs @@ -56,14 +56,14 @@ impl SharedStore { pub async fn restore(&mut self) -> Result<(), Error> { let mut inner = self.inner.write().await; - let invalid_registry: Option = inner + let unvalidated_registry: Option = inner .db .get(Key::Registry.to_prefixed_bytes())? .map(|b| decode_from_slice(b.as_slice(), config::standard())) .transpose()? .map(|(r, _)| r); - if let Some(invalid_reg) = invalid_registry { + if let Some(invalid_reg) = unvalidated_registry { inner.registry = invalid_reg.validate()?; debug!("loaded registry"); } diff --git a/bothan-kraken/src/api/websocket.rs b/bothan-kraken/src/api/websocket.rs index 2173f915..8844a062 100644 --- a/bothan-kraken/src/api/websocket.rs +++ b/bothan-kraken/src/api/websocket.rs @@ -30,7 +30,7 @@ impl KrakenWebSocketConnector { let status = resp.status(); if StatusCode::is_server_error(&status) || StatusCode::is_client_error(&status) { - warn!("Failed to connect with response code {}", resp.status()); + warn!("failed to connect with response code {}", resp.status()); return Err(ConnectionError::UnsuccessfulHttpResponse(resp.status())); } diff --git a/bothan-okx/src/api/websocket.rs b/bothan-okx/src/api/websocket.rs index f6b80a12..a2d385ff 100644 --- a/bothan-okx/src/api/websocket.rs +++ b/bothan-okx/src/api/websocket.rs @@ -28,7 +28,7 @@ impl OkxWebSocketConnector { let status = resp.status(); if StatusCode::is_server_error(&status) || StatusCode::is_client_error(&status) { - warn!("Failed to connect with response code {}", resp.status()); + warn!("failed to connect with response code {}", resp.status()); return Err(Error::ConnectionFailure(resp.status())); } diff --git a/bothan-okx/src/service.rs b/bothan-okx/src/service.rs index 836b6467..da29082e 100644 --- a/bothan-okx/src/service.rs +++ b/bothan-okx/src/service.rs @@ -76,7 +76,7 @@ impl Service for OkxService { .collect(); if !sub_ids.is_empty() && self.cmd_tx.send(Command::Subscribe(sub_ids)).await.is_err() { - warn!("Failed to send subscribe command"); + warn!("failed to send subscribe command"); } result @@ -138,7 +138,7 @@ async fn process_command( let vec_ids = ids.iter().map(|x| x.as_str()).collect::>(); let mut locked = ws.lock().await; if locked.subscribe_ticker(vec_ids.as_slice()).await.is_err() { - warn!("Failed to subscribe to ids: {:?}", ids); + warn!("failed to subscribe to ids: {:?}", ids); } } }