use std::sync::Arc; use anyhow::Context; use tracing::info; use tracing_subscriber::EnvFilter; use whoareyou_server::config::AppConfig; use whoareyou_server::fetch::ReqwestFetcher; use whoareyou_server::service::{LookupService, ProviderHandle}; use whoareyou_server::{http, wasm}; #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt() .with_env_filter( EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), ) .init(); let config = AppConfig::from_env()?; let engine = wasm::engine()?; let linker = wasm::linker(&engine)?; wasm::spawn_epoch_thread(&engine); let mut providers: Vec> = Vec::new(); let dir = std::fs::read_dir(&config.components_dir) .with_context(|| format!("reading components dir {:?}", config.components_dir))?; for entry in dir { let path = entry?.path(); if path.extension().is_some_and(|ext| ext == "wasm") { let provider = wasm::WasmProvider::load(&engine, &linker, &path) .with_context(|| format!("loading component {path:?}"))?; info!( name = provider.name(), version = provider.version(), ?path, "loaded provider" ); providers.push(Arc::new(provider)); } } anyhow::ensure!( !providers.is_empty(), "no .wasm components found in {:?}", config.components_dir ); let fetcher = Arc::new(ReqwestFetcher::new(config.fetch_timeout)?); let service = Arc::new(LookupService::new(providers, fetcher, config.cache_ttl)); let app = http::router(service); let listener = tokio::net::TcpListener::bind(config.listen).await?; info!("listening on http://{}", config.listen); axum::serve(listener, app).await?; Ok(()) }