Skip to main content

lora_server/
app.rs

1use std::sync::Arc;
2
3use anyhow::Result;
4use axum::{
5    routing::{get, post},
6    Router,
7};
8use lora_database::QueryRunner;
9
10mod admin;
11mod errors;
12mod routes;
13mod types;
14
15pub use admin::{AdminConfig, SnapshotAdminConfig};
16pub use errors::ErrorResponse;
17pub use types::{
18    HealthResponse, QueryFormat, QueryRequest, SnapshotRequest, SnapshotResponse,
19    WalStatusResponse, WalTruncateRequest,
20};
21
22pub fn build_app<R>(db: Arc<R>) -> Router
23where
24    R: QueryRunner,
25{
26    Router::new()
27        .route("/health", get(routes::health))
28        .route("/query", post(routes::query::<R>))
29        .route("/explain", post(routes::explain::<R>))
30        .route("/profile", post(routes::profile::<R>))
31        .with_state(db)
32}
33
34pub async fn serve<R>(listener: tokio::net::TcpListener, db: Arc<R>) -> Result<()>
35where
36    R: QueryRunner,
37{
38    let app = build_app(db);
39    axum::serve(listener, app).await?;
40    Ok(())
41}
42
43/// Same as [`build_app`] but additionally mounts the admin routes when
44/// `admin_config` is `Some`.
45pub fn build_app_with_admin<R>(db: Arc<R>, admin_config: Option<AdminConfig>) -> Router
46where
47    R: QueryRunner,
48{
49    let router = build_app(db);
50    match admin_config {
51        Some(cfg) => router.merge(admin::build_admin_router(cfg)),
52        None => router,
53    }
54}
55
56pub async fn serve_with_admin<R>(
57    listener: tokio::net::TcpListener,
58    db: Arc<R>,
59    admin_config: Option<AdminConfig>,
60) -> Result<()>
61where
62    R: QueryRunner,
63{
64    let app = build_app_with_admin(db, admin_config);
65    axum::serve(listener, app).await?;
66    Ok(())
67}