server
Some checks failed
Build and publish Docker image / build-and-push (push) Failing after 6m7s
CI / Check (push) Failing after 7m21s

This commit is contained in:
Andras Schmelczer 2026-05-31 13:19:26 +01:00
parent 8dc939d761
commit d98819b569
12 changed files with 157 additions and 161 deletions

View file

@ -171,6 +171,10 @@ struct Cli {
#[arg(long, env = "SATELLITE_TILES")]
satellite_tiles: Option<PathBuf>,
/// Optional PMTiles raster overlay for high-resolution EA aerial photography.
#[arg(long, env = "SATELLITE_HIGHRES_TILES")]
satellite_highres_tiles: Option<PathBuf>,
/// Optional PMTiles raster overlay for high-resolution strategic noise.
#[arg(long, env = "NOISE_OVERLAY_TILES")]
noise_overlay_tiles: Option<PathBuf>,
@ -183,6 +187,10 @@ struct Cli {
#[arg(long, env = "TREE_OVERLAY_TILES")]
tree_overlay_tiles: Option<PathBuf>,
/// Optional PMTiles vector overlay for INSPIRE property-border polygons.
#[arg(long, env = "PROPERTY_BORDER_TILES")]
property_border_tiles: Option<PathBuf>,
/// Path to the frontend dist directory (optional; disables static serving and OG injection when omitted)
#[arg(long)]
dist: Option<PathBuf>,
@ -300,34 +308,31 @@ async fn capture_server_error_responses(
response
}
async fn init_optional_tile_reader(
async fn init_required_tile_reader(
label: &'static str,
path: Option<&PathBuf>,
) -> anyhow::Result<Option<Arc<routes::TileReader>>> {
let Some(path) = path else {
info!("{label} overlay tiles not configured");
return Ok(None);
};
path: &Path,
) -> anyhow::Result<Arc<routes::TileReader>> {
if !path.exists() {
bail!("{label} overlay PMTiles not found: {}", path.display());
bail!("{label} PMTiles not found: {}", path.display());
}
info!("Loading {label} overlay PMTiles from {}", path.display());
Ok(Some(Arc::new(routes::init_tile_reader(path).await?)))
info!("Loading {label} PMTiles from {}", path.display());
Ok(Arc::new(routes::init_tile_reader(path).await?))
}
fn configured_or_default_overlay_path(
configured: &Option<PathBuf>,
tiles_path: &Path,
file_name: &str,
) -> Option<PathBuf> {
) -> PathBuf {
if let Some(path) = configured {
return Some(path.clone());
return path.clone();
}
let default_path = tiles_path.parent()?.join(file_name);
default_path.exists().then_some(default_path)
tiles_path
.parent()
.map(|parent| parent.join(file_name))
.unwrap_or_else(|| PathBuf::from(file_name))
}
#[tokio::main]
@ -481,6 +486,11 @@ async fn main() -> anyhow::Result<()> {
);
let satellite_tiles =
configured_or_default_overlay_path(&cli.satellite_tiles, tiles_path, "satellite.pmtiles");
let satellite_highres_tiles = configured_or_default_overlay_path(
&cli.satellite_highres_tiles,
tiles_path,
"satellite_highres.pmtiles",
);
let crime_hotspot_tiles = configured_or_default_overlay_path(
&cli.crime_hotspot_tiles,
tiles_path,
@ -491,14 +501,23 @@ async fn main() -> anyhow::Result<()> {
tiles_path,
"trees_outside_woodlands.pmtiles",
);
let property_border_tiles = configured_or_default_overlay_path(
&cli.property_border_tiles,
tiles_path,
"property_borders.pmtiles",
);
let noise_overlay_reader =
init_optional_tile_reader("Noise", noise_overlay_tiles.as_ref()).await?;
let satellite_reader = init_optional_tile_reader("Satellite", satellite_tiles.as_ref()).await?;
init_required_tile_reader("Noise", &noise_overlay_tiles).await?;
let satellite_reader = init_required_tile_reader("Satellite", &satellite_tiles).await?;
let satellite_highres_reader =
init_required_tile_reader("Satellite high-res", &satellite_highres_tiles).await?;
let crime_hotspot_reader =
init_optional_tile_reader("Crime hotspots", crime_hotspot_tiles.as_ref()).await?;
init_required_tile_reader("Crime hotspots", &crime_hotspot_tiles).await?;
let tree_overlay_reader =
init_optional_tile_reader("Trees outside woodland", tree_overlay_tiles.as_ref()).await?;
init_required_tile_reader("Trees outside woodland", &tree_overlay_tiles).await?;
let property_border_reader =
init_required_tile_reader("Property borders", &property_border_tiles).await?;
let feature_name_to_index: rustc_hash::FxHashMap<String, usize> = property_data
.feature_names
@ -700,9 +719,11 @@ async fn main() -> anyhow::Result<()> {
let reader_tile = tile_reader.clone();
let reader_style = tile_reader.clone();
let reader_satellite = satellite_reader.clone();
let reader_satellite_highres = satellite_highres_reader.clone();
let reader_noise_overlay = noise_overlay_reader.clone();
let reader_crime_hotspot = crime_hotspot_reader.clone();
let reader_tree_overlay = tree_overlay_reader.clone();
let reader_property_border = property_border_reader.clone();
let public_url_tiles = initial_state.public_url.clone();
let api = Router::new()
@ -878,6 +899,18 @@ async fn main() -> anyhow::Result<()> {
})
.layer(ConcurrencyLimitLayer::new(30)),
)
.route(
"/api/tiles/satellite-highres/{z}/{x}/{y}",
get(move |path| {
routes::get_overlay_tile(
reader_satellite_highres.clone(),
routes::OverlayTileFormat::RasterWebp,
"satellite-highres",
path,
)
})
.layer(ConcurrencyLimitLayer::new(30)),
)
.route(
"/api/overlays/noise/{z}/{x}/{y}",
get(move |path| {
@ -914,6 +947,18 @@ async fn main() -> anyhow::Result<()> {
})
.layer(ConcurrencyLimitLayer::new(30)),
)
.route(
"/api/overlays/property-borders/{z}/{x}/{y}",
get(move |path| {
routes::get_overlay_tile(
reader_property_border.clone(),
routes::OverlayTileFormat::VectorMvtGzip,
"property-borders",
path,
)
})
.layer(ConcurrencyLimitLayer::new(30)),
)
.route("/health", get(|| async { "ok" }))
.route(
"/metrics",