Files
endorphin-aster-vm/crates/server/src/main.rs
T
codex-bot e52d2e1e4b
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 7m25s
Separate database connections from file-backed host information and document handoff
2026-10-19 02:07:36 +08:00

78 lines
2.0 KiB
Rust

use std::error::Error;
use std::future::Future;
use std::process::ExitCode;
use std::sync::Arc;
use axum::{Json, Router, extract::State, routing::get};
use endor_core::Vm;
use host::MetadataStore;
use serde::Serialize;
#[derive(Clone)]
struct AppState {
vm: Arc<Vm>,
}
#[derive(Serialize)]
struct Health {
status: &'static str,
}
#[derive(Serialize)]
struct BootstrapInfo {
object_model: &'static str,
type_system: bool,
heap_objects: usize,
}
#[tokio::main]
async fn main() -> ExitCode {
match run().await {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("server: {error}");
ExitCode::FAILURE
}
}
}
async fn run() -> Result<(), Box<dyn Error>> {
let vm = Arc::new(Vm::new()?);
let address = std::env::var("ASTER_LISTEN").unwrap_or_else(|_| "127.0.0.1:8080".into());
let listener = tokio::net::TcpListener::bind(&address).await?;
let shutdown = shutdown_signal()?;
MetadataStore::from_env()?.put("host.version", env!("CARGO_PKG_VERSION"))?;
let app = Router::new()
.route("/health", get(health))
.route("/bootstrap", get(bootstrap))
.with_state(AppState { vm });
println!("Endor host listening on {}", listener.local_addr()?);
axum::serve(listener, app)
.with_graceful_shutdown(shutdown)
.await?;
Ok(())
}
async fn health() -> Json<Health> {
Json(Health { status: "ok" })
}
async fn bootstrap(State(state): State<AppState>) -> Json<BootstrapInfo> {
Json(BootstrapInfo {
object_model: "EndorObject",
type_system: false,
heap_objects: state.vm.object_count(),
})
}
fn shutdown_signal() -> std::io::Result<impl Future<Output = ()>> {
#[cfg(unix)]
let mut terminate = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())?;
Ok(async move {
#[cfg(unix)]
tokio::select! { _ = tokio::signal::ctrl_c() => {}, _ = terminate.recv() => {} }
#[cfg(not(unix))]
let _ = tokio::signal::ctrl_c().await;
})
}