Rewrite server in rust
This commit is contained in:
parent
0cea9b873c
commit
bf2d5de156
13 changed files with 3875 additions and 547 deletions
109
server-rs/src/main.rs
Normal file
109
server-rs/src/main.rs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
mod consts;
|
||||
mod data;
|
||||
mod index;
|
||||
mod routes;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use tower_http::compression::CompressionLayer;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
use routes::AppState;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let parquet_path = PathBuf::from(
|
||||
std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or_else(|| "data_sources/processed/wide.parquet".to_string()),
|
||||
);
|
||||
if !parquet_path.exists() {
|
||||
eprintln!("Error: {} not found.", parquet_path.display());
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// Load property data and build indices
|
||||
let property_data = data::PropertyData::load(&parquet_path);
|
||||
let grid = index::GridIndex::build(&property_data.lat, &property_data.lon, 0.01);
|
||||
let h3_cells = data::precompute_h3(&property_data.lat, &property_data.lon);
|
||||
|
||||
// Load POI data and build spatial index
|
||||
// Derive POI path from the data parquet path (same directory)
|
||||
let poi_path = parquet_path
|
||||
.parent()
|
||||
.and_then(|p| p.parent())
|
||||
.map(|p| p.join("filtered_uk_pois.parquet"))
|
||||
.unwrap_or_else(|| PathBuf::from("data_sources/filtered_uk_pois.parquet"));
|
||||
|
||||
let poi_data = if poi_path.exists() {
|
||||
data::POIData::load(&poi_path)
|
||||
} else {
|
||||
eprintln!("Warning: {} not found. POI endpoints will be unavailable.", poi_path.display());
|
||||
data::POIData {
|
||||
id: Vec::new(),
|
||||
name: Vec::new(),
|
||||
category: Vec::new(),
|
||||
lat: Vec::new(),
|
||||
lng: Vec::new(),
|
||||
emoji: Vec::new(),
|
||||
}
|
||||
};
|
||||
let poi_grid = index::GridIndex::build(&poi_data.lat, &poi_data.lng, 0.01);
|
||||
|
||||
let state = Arc::new(AppState {
|
||||
data: property_data,
|
||||
grid,
|
||||
h3_cells,
|
||||
poi_data,
|
||||
poi_grid,
|
||||
});
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods(Any)
|
||||
.allow_headers(Any);
|
||||
|
||||
// API routes
|
||||
let state_features = state.clone();
|
||||
let state_hexagons = state.clone();
|
||||
let state_pois = state.clone();
|
||||
let state_poi_categories = state.clone();
|
||||
|
||||
let api = Router::new()
|
||||
.route(
|
||||
"/api/features",
|
||||
get(move || routes::get_features(state_features.clone())),
|
||||
)
|
||||
.route(
|
||||
"/api/hexagons",
|
||||
get(move |query| routes::get_hexagons(state_hexagons.clone(), query)),
|
||||
)
|
||||
.route(
|
||||
"/api/pois",
|
||||
get(move |query| routes::get_pois(state_pois.clone(), query)),
|
||||
)
|
||||
.route(
|
||||
"/api/poi-categories",
|
||||
get(move || routes::get_poi_categories(state_poi_categories.clone())),
|
||||
);
|
||||
|
||||
// Static file serving for frontend
|
||||
let frontend_dist = PathBuf::from("frontend/dist");
|
||||
let app = if frontend_dist.exists() {
|
||||
api.fallback_service(ServeDir::new(frontend_dist))
|
||||
} else {
|
||||
api
|
||||
};
|
||||
|
||||
let app = app.layer(cors).layer(CompressionLayer::new().gzip(true));
|
||||
|
||||
let addr = "0.0.0.0:8001";
|
||||
eprintln!("Server listening on {}", addr);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue