Fix POI distance calculation reliability for remote/Celery execution
- Fix silent log loss: replace hardcoded "uvicorn.error" logger with __name__ in osrm_client, otp_client, poi_distance_calculator, and poi_tasks (uvicorn logger has no handlers in Celery worker, so all errors were silently dropped) - Add Celery retry: autoretry_for=(Exception,), max_retries=3, retry_backoff - Add top-level exception handling in task with full traceback logging - Fix upsert_distances: replace session.merge() (PK-based) with proper dialect-aware INSERT ON DUPLICATE KEY UPDATE / ON CONFLICT DO UPDATE - Filter out listings with null/zero coordinates before routing - Raise OSError when all routing engines fail with 0 results computed, distinguishing "nothing to compute" from "all engines unreachable"
This commit is contained in:
parent
46995cb9da
commit
5b566bab4c
5 changed files with 85 additions and 16 deletions
|
|
@ -15,7 +15,7 @@ from rec.otp_client import otp_transit_route
|
|||
from repositories.listing_repository import ListingRepository
|
||||
from repositories.poi_repository import POIRepository
|
||||
|
||||
logger = logging.getLogger("uvicorn.error")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Map travel mode names to OSRM profiles
|
||||
_OSRM_PROFILES = {
|
||||
|
|
@ -61,8 +61,25 @@ async def calculate_poi_distances(
|
|||
logger.info("No listings found for distance calculation")
|
||||
return 0
|
||||
|
||||
# Filter out listings without valid coordinates
|
||||
valid_listings = [
|
||||
l for l in listings
|
||||
if l.latitude is not None and l.longitude is not None
|
||||
and l.latitude != 0 and l.longitude != 0
|
||||
]
|
||||
if len(valid_listings) < len(listings):
|
||||
logger.warning(
|
||||
f"Skipped {len(listings) - len(valid_listings)} listings "
|
||||
f"with missing coordinates"
|
||||
)
|
||||
listings = valid_listings
|
||||
if not listings:
|
||||
logger.warning("No listings with valid coordinates")
|
||||
return 0
|
||||
|
||||
total_computed = 0
|
||||
total_modes = len(travel_modes)
|
||||
modes_failed: list[str] = []
|
||||
|
||||
for mode_idx, mode in enumerate(travel_modes):
|
||||
mode_upper = mode.upper()
|
||||
|
|
@ -105,6 +122,7 @@ async def calculate_poi_distances(
|
|||
continue
|
||||
except (aiohttp.ClientError, OSError) as e:
|
||||
logger.error(f"Routing engine unreachable for {mode_upper}: {e}")
|
||||
modes_failed.append(mode_upper)
|
||||
if on_progress:
|
||||
on_progress(
|
||||
total_computed, len(listings) * total_modes,
|
||||
|
|
@ -114,6 +132,13 @@ async def calculate_poi_distances(
|
|||
|
||||
total_computed += computed
|
||||
|
||||
if modes_failed and total_computed == 0:
|
||||
failed_str = ", ".join(modes_failed)
|
||||
raise OSError(
|
||||
f"All routing engines failed ({failed_str}). "
|
||||
f"No distances computed for {len(listings)} listings."
|
||||
)
|
||||
|
||||
return total_computed
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue