78 lines
2.0 KiB
Rust
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;
|
|
})
|
|
}
|