Fix crime & add actual listings
Some checks failed
CI / Check (push) Failing after 4m1s
Build and publish Docker image / build-and-push (push) Failing after 4m10s

This commit is contained in:
Andras Schmelczer 2026-05-17 11:12:25 +01:00
parent 017902b8e6
commit ebe7bbb51d
34 changed files with 2014 additions and 172754 deletions

View file

@ -0,0 +1,80 @@
use std::sync::Arc;
use axum::extract::{Query, State};
use axum::http::StatusCode;
use axum::response::Json;
use serde::{Deserialize, Serialize};
use tracing::info;
use crate::data::ActualListing;
use crate::parsing::require_bounds;
use crate::state::SharedState;
const MAX_RESULTS: usize = 5000;
#[derive(Deserialize)]
pub struct ActualListingsParams {
bounds: Option<String>,
}
#[derive(Serialize)]
pub struct ActualListingsResponse {
pub listings: Vec<ActualListing>,
pub total: usize,
pub truncated: bool,
}
pub async fn get_actual_listings(
State(shared): State<Arc<SharedState>>,
Query(params): Query<ActualListingsParams>,
) -> Result<Json<ActualListingsResponse>, (StatusCode, String)> {
let state = shared.load_state();
let Some(actual_listings) = state.actual_listings.clone() else {
return Ok(Json(ActualListingsResponse {
listings: Vec::new(),
total: 0,
truncated: false,
}));
};
let (south, west, north, east) = require_bounds(params.bounds)?;
let response = tokio::task::spawn_blocking(move || {
let t0 = std::time::Instant::now();
let row_indices = actual_listings.grid.query(south, west, north, east);
let total = row_indices.len();
let truncated = total > MAX_RESULTS;
let mut listings: Vec<ActualListing> = row_indices
.iter()
.take(MAX_RESULTS)
.map(|&row| actual_listings.listing_at(row as usize))
.collect();
// Sort newest first so the most relevant pins win when the viewport is busy.
listings.sort_by(|left, right| {
right
.listing_date_iso
.cmp(&left.listing_date_iso)
.then_with(|| right.asking_price.cmp(&left.asking_price))
});
let elapsed = t0.elapsed();
info!(
results = listings.len(),
total,
truncated,
ms = format_args!("{:.1}", elapsed.as_secs_f64() * 1000.0),
"GET /api/actual-listings"
);
ActualListingsResponse {
listings,
total,
truncated,
}
})
.await
.map_err(|error| (StatusCode::INTERNAL_SERVER_ERROR, error.to_string()))?;
Ok(Json(response))
}