redvault-ai/llama_forge_rs/src/server/mod.rs
Tristan Druyen 8d8923294d
feat: Embedded proxy_man for forge
- Add `figment` for config yamls
- Small `Makefile.toml` fixes ? (docset seems still broken ??)
- Copy `config.yaml` workspace & forge
- Embed proxy_man in forge
- Remove `backend_process.rs` and `process.rs`
- Update `llama_proxy_man/Cargo.toml` and `config.rs` for new dependencies
- Format
2025-02-11 04:24:43 +01:00

161 lines
4.7 KiB
Rust

use std::str::FromStr;
use axum::{
body::Body,
extract::{DefaultBodyLimit, FromRef, Path, State},
http::Request,
response::IntoResponse,
routing::get,
Extension, Router,
};
use leptos::*;
use leptos_axum::{generate_route_list, handle_server_fns_with_context, LeptosRoutes};
use leptos_router::RouteListing;
use sqlx::{
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous},
ConnectOptions, SqlitePool,
};
use tower::Layer;
use tower_http::{
compression::CompressionLayer,
trace::{
DefaultMakeSpan, DefaultOnEos, DefaultOnFailure, DefaultOnRequest, DefaultOnResponse,
TraceLayer,
},
CompressionLevel,
};
use tracing::Level;
use self::fileserv::file_and_error_handler;
use crate::{
app::*,
server::middleware::{LoggingLayer, LoggingService},
};
pub mod backends;
mod fileserv;
mod middleware;
pub fn pool() -> Result<SqlitePool, ServerFnError> {
use_context::<SqlitePool>().ok_or_else(|| ServerFnError::ServerError("Pool missing.".into()))
}
#[derive(FromRef, Debug, Clone)]
pub struct AppState {
pub leptos_options: LeptosOptions,
pub pool: SqlitePool,
pub routes: Vec<RouteListing>,
}
pub async fn server_fn_handler(
State(app_state): State<AppState>,
path: Path<String>,
request: Request<Body>,
) -> impl IntoResponse {
tracing::debug!("handling server_fn {:?}", path);
handle_server_fns_with_context(
move || {
provide_context(app_state.pool.clone());
},
request,
)
.await
}
pub async fn leptos_routes_handler(
State(app_state): State<AppState>,
req: Request<Body>,
) -> impl IntoResponse {
tracing::debug!("handling leptos_route: {:?}", req);
let handler = leptos_axum::render_route_with_context(
app_state.leptos_options.clone(),
app_state.routes.clone(),
move || {
provide_context(app_state.pool.clone());
},
App,
);
let response = handler(req).await;
tracing::debug!("leptos_route response: {:?}", response);
response
}
pub async fn app(leptos_options: LeptosOptions) -> Router {
async fn new_pool() -> Result<SqlitePool, Box<dyn std::error::Error>> {
// TODO Save this in xdg_config_dir /data dir
let db_options = SqliteConnectOptions::from_str("sqlite:db.sqlite3")?
.create_if_missing(true)
.optimize_on_close(true, None)
.journal_mode(SqliteJournalMode::Wal)
.synchronous(SqliteSynchronous::Normal)
.disable_statement_logging()
.busy_timeout(std::time::Duration::from_secs(16))
.statement_cache_capacity(512)
.to_owned();
tracing::debug!(
msg = "Connectiong to db",
conn_str = ?db_options.to_url_lossy()
);
let pool = SqlitePoolOptions::new().connect_with(db_options).await?;
sqlx::migrate!()
.run(&pool)
.await
.expect("could not run SQLx migrations");
Ok(pool)
}
let routes = generate_route_list(App);
let pool = new_pool().await.expect("pool err");
// // TODO move this out of server(pool has to be moved out too)
// FIXME: Should proxy_man move here ?
// let task = run_starter_task(pool.clone());
// tokio::task::spawn(task);
let app_state = AppState {
leptos_options,
// stream_registry: Arc::default(),
pool: pool.clone(),
routes: routes.clone(),
};
const MAX_BODY_LIMIT: usize = 16 * 1024 * 1024; // 16 MB
tracing::debug!("routes: {:?}", routes);
// build our application with a route
Router::new()
.route(
"/api/*fn_name",
get(server_fn_handler).post(server_fn_handler),
)
.leptos_routes_with_handler(routes, get(leptos_routes_handler))
.fallback(file_and_error_handler)
.with_state(app_state)
.layer(Extension(pool))
.layer(
// Todo Readd gzip & deflate and add compress_when which skips them if response is a stream
CompressionLayer::new()
.no_gzip()
.no_deflate()
.quality(CompressionLevel::Fastest),
)
.layer(
TraceLayer::new_for_http()
.make_span_with(DefaultMakeSpan::new().include_headers(true))
.on_request(DefaultOnRequest::new().level(Level::INFO))
.on_response(DefaultOnResponse::new().level(Level::INFO))
.on_eos(DefaultOnEos::new().level(Level::DEBUG))
.on_failure(DefaultOnFailure::new().level(Level::ERROR)),
)
.layer(DefaultBodyLimit::max(MAX_BODY_LIMIT))
.layer(LoggingLayer)
}