summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs94
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(())
}