From 74d96476897abd30f656a299ce311bfd58d6ce7d Mon Sep 17 00:00:00 2001 From: core Date: Thu, 15 May 2025 07:14:41 -0400 Subject: [PATCH] feat: ssr --- Cargo.lock | 15 +++++++++++++++ client/src/lib/Map.svelte | 12 ++++++++++++ crates/ar2/src/lib.rs | 1 + crates/tiler/Cargo.toml | 1 + crates/tiler/config.toml | 4 ++-- crates/tiler/src/main.rs | 11 +++++++++-- crates/tiler/src/nexrad.rs | 29 ++++++++++++++++++++--------- 7 files changed, 60 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9044a0..a55f660 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4972,6 +4972,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" +dependencies = [ + "bitflags 2.9.0", + "bytes", + "http", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -6330,6 +6344,7 @@ dependencies = [ "strum_macros 0.27.1", "tokio", "toml", + "tower-http", "tracing", "tracing-subscriber", "wxbox-ar2", diff --git a/client/src/lib/Map.svelte b/client/src/lib/Map.svelte index e30ad2c..cf0b1f8 100644 --- a/client/src/lib/Map.svelte +++ b/client/src/lib/Map.svelte @@ -31,6 +31,18 @@ img.onload = () => { map?.addImage('radar-rect-gray', img); }; + map.addSource('kcys-bref-0.5', { + type: 'raster', + tiles: [ + 'http://localhost:3000/nexrad/base_reflectivity_halfdegree/KCYS/{z}/{x}/{y}@2x.png' + ], + 'tileSize': 512 + }); + map.addLayer({ + id: 'kcys', + type: 'raster', + source: 'kcys-bref-0.5' + }); }); }); diff --git a/crates/ar2/src/lib.rs b/crates/ar2/src/lib.rs index 4a49e29..d023935 100644 --- a/crates/ar2/src/lib.rs +++ b/crates/ar2/src/lib.rs @@ -87,6 +87,7 @@ pub fn parse(input: Vec) -> nexrad_data::result::Result { let mut vcp = None; let mut radials = vec![]; + println!("{:?}", file.header()); for mut record in file.records() { if record.compressed() { record = record.decompress()?; diff --git a/crates/tiler/Cargo.toml b/crates/tiler/Cargo.toml index c122dcb..bfea8c3 100644 --- a/crates/tiler/Cargo.toml +++ b/crates/tiler/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # web server tokio = { version = "1", features = ["full"] } axum = "0.8" +tower-http = { version = "0.6", features = ["cors"]} # caching moka = { version = "0.12", features = ["future"] } diff --git a/crates/tiler/config.toml b/crates/tiler/config.toml index cc00c4c..dcc43a5 100644 --- a/crates/tiler/config.toml +++ b/crates/tiler/config.toml @@ -15,8 +15,8 @@ Color: 80 128 128 128 missing = -99.0 no_coverage = -999.0 -[data.nexrad.l2_reflectivity] -from = "aaaa" +[data.nexrad.base_reflectivity_halfdegree] +from = "DS.p94r0" palette = """ Color: 5 0x40 0xe8 0xe3 Color: 10 0x26 0xa4 0xfa diff --git a/crates/tiler/src/main.rs b/crates/tiler/src/main.rs index a8c99c3..4f380b7 100644 --- a/crates/tiler/src/main.rs +++ b/crates/tiler/src/main.rs @@ -14,6 +14,8 @@ use moka::future::Cache; use std::env::args; use std::fmt::{Debug, Formatter}; use std::sync::Arc; +use axum::http::Method; +use tower_http::cors::{Any, CorsLayer}; use tracing_subscriber::fmt::format::FmtSpan; use tracing_subscriber::util::SubscriberInitExt; use wxbox_grib2::GribMessage; @@ -58,11 +60,16 @@ async fn main() -> anyhow::Result<()> { config: Arc::new(config), }; + let cors = CorsLayer::new() + .allow_methods([Method::GET]) + .allow_origin(Any); + let app = Router::new() .route("/grib2/{source}/{z}/{x}/{y}", get(grib2_handler)) .route("/grib2/{source}/metadata", get(grib2_metadata)) - .route("/nexrad/{source}/{z}/{x}/{y}", get(nexrad_handler)) - .with_state(state); + .route("/nexrad/{source}/{site}/{z}/{x}/{y}", get(nexrad_handler)) + .with_state(state) + .layer(cors); let listener = tokio::net::TcpListener::bind("[::]:3000").await?; axum::serve(listener, app).await?; diff --git a/crates/tiler/src/nexrad.rs b/crates/tiler/src/nexrad.rs index 788ab3e..06522d8 100644 --- a/crates/tiler/src/nexrad.rs +++ b/crates/tiler/src/nexrad.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::f64::consts::PI; use std::fmt::Debug; -use std::io; +use std::{fs, io}; use std::io::{Cursor, ErrorKind}; use std::num::TryFromIntError; use std::sync::Arc; @@ -46,7 +46,7 @@ impl Debug for NexradDataSource { #[tracing::instrument(level = "info")] pub async fn nexrad_handler( - Path((source, z, x, y)): Path<(String, usize, usize, String)>, + Path((source, site, z, x, y)): Path<(String, String, usize, usize, String)>, State(state): State, ) -> Result { let mut y = y @@ -59,7 +59,7 @@ pub async fn nexrad_handler( } let y: usize = y.parse()?; let tile_id = TileId { - source, + source: format!("{source}/{site}"), z, x, y, @@ -73,7 +73,7 @@ pub async fn nexrad_handler( // is this even a valid data source? let data_id = tile_id.data_id(); - let Some(ds) = state.config.data.nexrad.get(&data_id.source) else { + let Some(ds) = state.config.data.nexrad.get(&source) else { return Err(anyhow!("invalid/unknown nexrad state").into()); }; @@ -82,7 +82,7 @@ pub async fn nexrad_handler( // lets check if we have the raw data let data = if !state.nexrad_data_cache.contains_key(&data_id) { // we don't, so let's start by starting a task for that - load_nexrad_data(state.nexrad_data_cache, data_id, ds.clone()).await? + load_nexrad_data(state.nexrad_data_cache, data_id, ds.clone(), &site).await? } else { state.nexrad_data_cache.get(&data_id).await.unwrap() }; @@ -90,7 +90,7 @@ pub async fn nexrad_handler( // we know we need to build the tile, so let's do that now // it also returns it, so we can conveniently return it right now let pixel_data = - render_to_png(state.nexrad_tile_cache.clone(), data, tile_id, ds.clone()).await?; + render_to_png(state.nexrad_tile_cache.clone(), data, tile_id, &site, ds.clone()).await?; Ok(( [(header::CONTENT_TYPE, "image/png")], @@ -102,10 +102,21 @@ async fn load_nexrad_data( cache: NexradDataCache, data_id: DataId, data_source: NexradDataSource, + site: &str, ) -> anyhow::Result> { let _load_span = info_span!("load_nexrad_data"); - let bytes = DATA_BYTES.to_vec(); + // todo: find the correct + let url = format!("https://noaa-nexrad-level2.s3.amazonaws.com/2025/05/15/KCYS/KCYS20250515_003010_V06"); + + let client = reqwest::Client::new(); + let r = client.get(url).send().await?; + + if !r.status().is_success() { + bail!("nexrad data failed to load: {}", r.status()); + } + + let bytes = r.bytes().await?.to_vec(); let data = Arc::new(parse(bytes)?); @@ -175,7 +186,7 @@ async fn render_to_png( cache: NexradTileCache, data: Arc, tile_id: TileId, - + site: &str, data_source: NexradDataSource, ) -> anyhow::Result>> { let span = info_span!("render_to_png"); @@ -192,7 +203,7 @@ async fn render_to_png( let first_sweep = data.sweeps.get(0).unwrap(); let g = Geodesic::wgs84(); - let radar = SITES.sites.get("KCRP").unwrap(); + let radar = SITES.sites.get(site).unwrap(); drop(prep_span);