diff options
| author | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-21 21:10:22 +0300 |
|---|---|---|
| committer | Dawid Rycerz <dawid@rycerz.xyz> | 2025-07-21 21:10:22 +0300 |
| commit | 934fb31059da10fa843d96a10c37f181eaa89456 (patch) | |
| tree | 452b36bdd1e286e68381607f15742695afec0f60 /src/main.rs | |
| parent | 30f50e5b31294abd75c4b629970ad4865108738d (diff) | |
feat: add weather pooler and config
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 94 |
1 files changed, 72 insertions, 22 deletions
diff --git a/src/main.rs b/src/main.rs index 4e89234..9f97e37 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,8 @@ use axum::{Router, routing::get}; use clap::{Parser, Subcommand}; use serde_json::json; use sqlx::SqlitePool; -use std::env; use std::net::SocketAddr; use std::sync::Arc; -use tokio::fs; use tracing::{error, info}; use tracing_subscriber::{EnvFilter, FmtSubscriber}; use utoipa::OpenApi; @@ -17,10 +15,12 @@ use utoipa_swagger_ui::SwaggerUi; use uuid::Uuid; mod auth; +mod config; mod health; mod locations; mod notifications; mod users; +mod weather_api_data; mod weather_poller; mod weather_thresholds; @@ -918,31 +918,42 @@ enum Commands { Server, /// Create a new user with optional UUID CreateUser { uuid: Option<String> }, + /// Manually trigger weather check for testing + CheckWeather, } #[tokio::main] async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); - // Set up logging based on verbosity - let filter = match cli.verbose { - 0 => "warn", - 1 => "info", - 2 => "debug", - _ => "trace", + + // Load configuration + let config = config::Config::from_env(); + + // Set up logging based on verbosity or config + let filter = if cli.verbose > 0 { + match cli.verbose { + 1 => "info", + 2 => "debug", + _ => "trace", + } + } else { + &config.log_level }; + let subscriber = FmtSubscriber::builder() .with_env_filter(EnvFilter::new(filter)) .finish(); tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); + + info!( + "Starting Silmataivas with database: {}", + config.database_url + ); + match cli.command.unwrap_or(Commands::Server) { Commands::Server => { - // Set up database path - let db_path = env::var("DATABASE_URL") - .unwrap_or_else(|_| "sqlite://./data/silmataivas.db".to_string()); - // Ensure data directory exists - let _ = fs::create_dir_all("./data").await; - // Connect to SQLite - let pool = SqlitePool::connect(&db_path) + // Connect to database + let pool = SqlitePool::connect(&config.database_url) .await .expect("Failed to connect to DB"); @@ -951,8 +962,9 @@ async fn main() -> anyhow::Result<()> { let repo = users::UserRepository { db: &pool }; match repo.any_admin_exists().await { Ok(false) => { - let admin_token = - env::var("ADMIN_TOKEN").unwrap_or_else(|_| Uuid::new_v4().to_string()); + let admin_token = config + .admin_token + .unwrap_or_else(|| Uuid::new_v4().to_string()); match repo .create_user(Some(admin_token.clone()), Some(users::UserRole::Admin)) .await @@ -970,17 +982,42 @@ async fn main() -> anyhow::Result<()> { } } - let app = app_with_state(Arc::new(pool)); - let addr = SocketAddr::from(([0, 0, 0, 0], 4000)); + let app = app_with_state(Arc::new(pool.clone())); + let addr = SocketAddr::from(( + config + .server_host + .parse::<std::net::IpAddr>() + .unwrap_or(std::net::IpAddr::V4(std::net::Ipv4Addr::new(0, 0, 0, 0))), + config.server_port, + )); let listener = tokio::net::TcpListener::bind(addr) .await .expect("Failed to bind address"); info!("Listening on {}", listener.local_addr().unwrap()); - axum::serve(listener, app).await.unwrap(); + + // Start the weather scheduler in the background + let scheduler = crate::weather_poller::WeatherScheduler::new(Arc::new(pool)); + let scheduler_handle = tokio::spawn(async move { + if let Err(e) = scheduler.start().await { + error!("Weather scheduler failed: {}", e); + } + }); + + // Start the web server + let server_handle = axum::serve(listener, app); + + // Wait for either the server or scheduler to fail + tokio::select! { + _ = server_handle => { + error!("Web server stopped"); + } + _ = scheduler_handle => { + error!("Weather scheduler stopped"); + } + } } Commands::CreateUser { uuid } => { - let db_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - let pool = SqlitePool::connect(&db_url).await?; + let pool = SqlitePool::connect(&config.database_url).await?; let repo = crate::users::UserRepository { db: &pool }; let user_id = uuid.unwrap_or_else(|| Uuid::new_v4().to_string()); let user = repo @@ -1037,6 +1074,19 @@ async fn main() -> anyhow::Result<()> { info!("User {} created", user_id); } + Commands::CheckWeather => { + let pool = SqlitePool::connect(&config.database_url) + .await + .expect("Failed to connect to DB"); + + let poller = crate::weather_poller::WeatherPoller::new(Arc::new(pool)); + info!("Manually triggering weather check..."); + + match poller.check_all().await { + Ok(()) => info!("Weather check completed successfully"), + Err(e) => error!("Weather check failed: {}", e), + } + } } Ok(()) } |
