Fix crime & add actual listings
This commit is contained in:
parent
017902b8e6
commit
ebe7bbb51d
34 changed files with 2014 additions and 172754 deletions
80
server-rs/src/routes/actual_listings.rs
Normal file
80
server-rs/src/routes/actual_listings.rs
Normal 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))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue