Refactor backend for cleaner error handling, DRY, and type safety
- Extract rate limiter DRY: consolidate 3 duplicated check/respond paths into _check_counter and _enforce_limit helpers, add proper type annotations - Replace bare Exception raises with FloorplanDownloadError and RightmoveApiError; narrow catch clauses to specific exception types; fix Step base class to inherit from ABC - Consolidate MAX_OCR_WORKERS into config/scraper_config.py; extract _find_tenure_value helper to deduplicate tenure parsing - Extract _build_poi_distances_lookup from stream endpoint to reduce nesting - Fix csv_exporter: optional decisions.json, NaN instead of -1 sentinels, guard against division by zero on missing square meters - Fix notifications.py broken list[Surface]() constructor, database.py stale comments and missing type annotation, auth.py type:ignore, ui_exporter.py stale TODO - Fix 3 pre-existing test failures: mock cache layer in streaming tests, bypass rate limiter for test isolation, fix cache invalidation test to account for two-pattern scan loop
This commit is contained in:
parent
6897820cc7
commit
f833309297
20 changed files with 199 additions and 178 deletions
61
api/app.py
61
api/app.py
|
|
@ -185,6 +185,40 @@ async def get_listing_geojson(
|
|||
|
||||
|
||||
|
||||
def _build_poi_distances_lookup(
|
||||
user_email: str,
|
||||
listing_type: ListingType,
|
||||
) -> dict[int, list[dict[str, str | int]]] | None:
|
||||
"""Build POI distance lookup for a user, or None if no POIs configured."""
|
||||
user_repo = UserRepository(engine)
|
||||
db_user = user_repo.get_user_by_email(user_email)
|
||||
if not db_user or db_user.id is None:
|
||||
return None
|
||||
|
||||
poi_repo = POIRepository(engine)
|
||||
pois = {p.id: p for p in poi_repo.get_pois_for_user(db_user.id)}
|
||||
if not pois:
|
||||
return None
|
||||
|
||||
listing_repo = ListingRepository(engine)
|
||||
all_ids = list(listing_repo.get_listing_ids(listing_type))
|
||||
if not all_ids:
|
||||
return None
|
||||
|
||||
distances = poi_repo.get_distances_for_listings(all_ids, listing_type, db_user.id)
|
||||
lookup: dict[int, list[dict[str, str | int]]] = {}
|
||||
for d in distances:
|
||||
poi_name = pois[d.poi_id].name if d.poi_id in pois else "Unknown"
|
||||
lookup.setdefault(d.listing_id, []).append({
|
||||
"poi_id": d.poi_id,
|
||||
"poi_name": poi_name,
|
||||
"travel_mode": d.travel_mode,
|
||||
"duration_seconds": d.duration_seconds,
|
||||
"distance_meters": d.distance_meters,
|
||||
})
|
||||
return lookup
|
||||
|
||||
|
||||
async def _stream_from_cache(
|
||||
query_parameters: QueryParameters,
|
||||
batch_size: int,
|
||||
|
|
@ -295,32 +329,7 @@ async def stream_listing_geojson(
|
|||
limit = _rate_limit_config.geojson_stream_limit_cap
|
||||
|
||||
# Build POI distances lookup if requested
|
||||
poi_distances_lookup: dict[int, list[dict[str, str | int]]] | None = None
|
||||
if include_poi_distances:
|
||||
user_repo = UserRepository(engine)
|
||||
db_user = user_repo.get_user_by_email(user.email)
|
||||
if db_user and db_user.id is not None:
|
||||
poi_repo = POIRepository(engine)
|
||||
pois = {p.id: p for p in poi_repo.get_pois_for_user(db_user.id)}
|
||||
if pois:
|
||||
# Get all listing IDs first for the query
|
||||
listing_repo = ListingRepository(engine)
|
||||
all_ids = list(listing_repo.get_listing_ids(query_parameters.listing_type))
|
||||
if all_ids:
|
||||
distances = poi_repo.get_distances_for_listings(
|
||||
all_ids, query_parameters.listing_type, db_user.id
|
||||
)
|
||||
poi_distances_lookup = {}
|
||||
for d in distances:
|
||||
poi_name = pois[d.poi_id].name if d.poi_id in pois else "Unknown"
|
||||
entry = {
|
||||
"poi_id": d.poi_id,
|
||||
"poi_name": poi_name,
|
||||
"travel_mode": d.travel_mode,
|
||||
"duration_seconds": d.duration_seconds,
|
||||
"distance_meters": d.distance_meters,
|
||||
}
|
||||
poi_distances_lookup.setdefault(d.listing_id, []).append(entry)
|
||||
poi_distances_lookup = _build_poi_distances_lookup(user.email, query_parameters.listing_type) if include_poi_distances else None
|
||||
|
||||
cached_count = get_cached_count(query_parameters)
|
||||
if cached_count is not None and cached_count > 0 and not include_poi_distances:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue