Checkpoint all changes

This commit is contained in:
Andras Schmelczer 2026-02-01 19:30:33 +00:00
parent 65877acf95
commit 66c2a25457
28 changed files with 3035 additions and 621 deletions

View file

@ -39,37 +39,56 @@ pub async fn get_pois(
let category_filter: Option<rustc_hash::FxHashSet<String>> = params
.categories
.as_deref()
.filter(|s| !s.is_empty())
.map(|s| s.split(',').map(|c| c.trim().to_string()).collect());
.filter(|text| !text.is_empty())
.map(|text| text.split(',').map(|part| part.trim().to_string()).collect());
let num_categories = category_filter.as_ref().map(|c| c.len()).unwrap_or(0);
let num_categories = category_filter.as_ref().map(|cats| cats.len()).unwrap_or(0);
let result = tokio::task::spawn_blocking(move || {
let t0 = std::time::Instant::now();
let row_indices = state.poi_grid.query(south, west, north, east);
let pois: Vec<POI> = row_indices
// Collect matching row indices first, then sample randomly so the
// subset covers the viewport uniformly instead of clustering in one area.
let mut matching_rows: Vec<usize> = row_indices
.iter()
.filter_map(|&row_idx| {
let row = row_idx as usize;
if let Some(ref categories) = category_filter {
if !categories.contains(&state.poi_data.category[row]) {
return None;
}
}
Some(POI {
id: state.poi_data.id[row].clone(),
name: state.poi_data.name[row].clone(),
category: state.poi_data.category[row].clone(),
group: state.poi_data.group[row].clone(),
lat: state.poi_data.lat[row],
lng: state.poi_data.lng[row],
emoji: state.poi_data.emoji[row].clone(),
})
Some(row)
})
.collect();
if matching_rows.len() > MAX_POIS_PER_REQUEST {
// Use a power-of-2 sampling step so each POI's inclusion depends
// only on its own priority hash, not on what other POIs are in
// the viewport. This prevents visible reshuffling when panning.
let ratio = (matching_rows.len() / MAX_POIS_PER_REQUEST) as u32;
let step = ratio.next_power_of_two();
let mask = step - 1;
matching_rows.retain(|&row| state.poi_data.priority[row] & mask == 0);
// Statistical noise may leave us slightly over the limit
if matching_rows.len() > MAX_POIS_PER_REQUEST {
matching_rows.sort_unstable_by_key(|&row| state.poi_data.priority[row]);
matching_rows.truncate(MAX_POIS_PER_REQUEST);
}
}
let pois: Vec<POI> = matching_rows
.iter()
.map(|&row| POI {
id: state.poi_data.id[row].clone(),
name: state.poi_data.name[row].clone(),
category: state.poi_data.category[row].clone(),
group: state.poi_data.group[row].clone(),
lat: state.poi_data.lat[row],
lng: state.poi_data.lng[row],
emoji: state.poi_data.emoji[row].clone(),
})
.take(MAX_POIS_PER_REQUEST)
.collect();
let elapsed = t0.elapsed();
@ -85,7 +104,7 @@ pub async fn get_pois(
POIsResponse { pois }
})
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
.map_err(|error| (StatusCode::INTERNAL_SERVER_ERROR, error.to_string()))?;
Ok(Json(result))
}
@ -98,7 +117,7 @@ pub struct POICategoriesResponse {
pub async fn get_poi_categories(state: Arc<AppState>) -> Json<POICategoriesResponse> {
let groups: Vec<POICategoryGroup> = state.poi_category_groups.clone();
let total: usize = groups.iter().map(|g| g.categories.len()).sum();
let total: usize = groups.iter().map(|group| group.categories.len()).sum();
info!(
count = total,
groups = groups.len(),