mod api;
mod config;
mod error;
mod grpc;
mod handlers;
mod http;
mod tui;
use anyhow::Result;
use tracing::info;
use tracing_subscriber::EnvFilter;
use config::Config;
use http::HttpServer;
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
)
.with_target(false)
.init();
info!("Starting Converge Runtime");
let config = Config::load()?;
info!(?config, "Configuration loaded");
let http_server = HttpServer::new(config.http.clone());
let http_handle = tokio::spawn(async move {
if let Err(e) = http_server.start().await {
tracing::error!(error = %e, "HTTP server failed");
}
});
#[cfg(feature = "grpc")]
{
let grpc_config = config.grpc();
let grpc_server = grpc::GrpcServer::new(grpc_config);
let grpc_handle = tokio::spawn(async move {
if let Err(e) = grpc_server.start().await {
tracing::error!(error = %e, "gRPC server failed");
}
});
tokio::select! {
_ = http_handle => {},
_ = grpc_handle => {},
}
return Ok(());
}
#[cfg(feature = "tui")]
{
let tui_config = config.tui();
let tui_app = tui::TuiApp::new(tui_config);
let tui_handle = tokio::spawn(async move {
if let Err(e) = tui_app.run().await {
tracing::error!(error = %e, "TUI failed");
}
});
tokio::select! {
_ = http_handle => {},
_ = tui_handle => {},
}
return Ok(());
}
http_handle
.await
.map_err(|e| anyhow::anyhow!("HTTP server task failed: {e}"))?;
Ok(())
}