use std::sync::Arc;
use anyhow::Result;
use sqlx::postgres::PgPoolOptions;
use sqlx::sqlite::SqlitePoolOptions;
use tracing::{error, info};
use runtara_core::config::Config;
use runtara_core::persistence::{Persistence, PostgresPersistence, SqlitePersistence};
use runtara_core::runtime::CoreRuntime;
#[tokio::main]
async fn main() -> Result<()> {
dotenvy::dotenv().ok();
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive("runtara_core=info".parse().unwrap()),
)
.init();
info!("Starting Runtara Core");
let config = Config::from_env().map_err(|e| {
error!("Configuration error: {}", e);
e
})?;
info!(
instance_addr = %config.http_addr,
max_instances = config.max_concurrent_instances,
"Configuration loaded"
);
info!("Connecting to database...");
let persistence: Arc<dyn Persistence> = if config.database_url.starts_with("postgres://")
|| config.database_url.starts_with("postgresql://")
{
let pool = PgPoolOptions::new()
.max_connections(10)
.connect(&config.database_url)
.await?;
info!("Database connection established (Postgres)");
let row: (i32,) = sqlx::query_as("SELECT 1").fetch_one(&pool).await?;
info!(result = row.0, "Database health check passed");
info!("Running database migrations...");
runtara_core::migrations::run_postgres(&pool).await?;
info!("Migrations completed");
Arc::new(PostgresPersistence::new(pool))
} else {
let pool = SqlitePoolOptions::new()
.max_connections(10)
.connect(&config.database_url)
.await?;
info!("Database connection established (SQLite)");
info!("Running database migrations...");
runtara_core::migrations::run_sqlite(&pool).await?;
info!("Migrations completed");
Arc::new(SqlitePersistence::new(pool))
};
let runtime = CoreRuntime::builder()
.persistence(persistence)
.bind_addr(config.http_addr)
.build()?
.start()
.await?;
info!(addr = %config.http_addr, "Runtara Core ready");
tokio::signal::ctrl_c().await?;
info!("Shutting down...");
runtime.shutdown().await?;
Ok(())
}