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
|
|
@ -52,9 +52,41 @@ class POIRepository:
|
|||
return True
|
||||
|
||||
def upsert_distances(self, distances: list[POIDistance]) -> None:
|
||||
"""Insert or update POI distances, handling duplicate unique constraints."""
|
||||
if not distances:
|
||||
return
|
||||
with Session(self.engine) as session:
|
||||
dialect = self.engine.dialect.name
|
||||
for dist in distances:
|
||||
session.merge(dist)
|
||||
values = {
|
||||
"listing_id": dist.listing_id,
|
||||
"listing_type": dist.listing_type,
|
||||
"poi_id": dist.poi_id,
|
||||
"travel_mode": dist.travel_mode,
|
||||
"duration_seconds": dist.duration_seconds,
|
||||
"distance_meters": dist.distance_meters,
|
||||
"computed_at": dist.computed_at,
|
||||
}
|
||||
if dialect == "mysql":
|
||||
from sqlalchemy.dialects.mysql import insert as mysql_insert
|
||||
stmt = mysql_insert(POIDistance).values(**values)
|
||||
stmt = stmt.on_duplicate_key_update(
|
||||
duration_seconds=stmt.inserted.duration_seconds,
|
||||
distance_meters=stmt.inserted.distance_meters,
|
||||
computed_at=stmt.inserted.computed_at,
|
||||
)
|
||||
else:
|
||||
from sqlalchemy.dialects.sqlite import insert as sqlite_insert
|
||||
stmt = sqlite_insert(POIDistance).values(**values)
|
||||
stmt = stmt.on_conflict_do_update(
|
||||
index_elements=["listing_id", "listing_type", "poi_id", "travel_mode"],
|
||||
set_={
|
||||
"duration_seconds": stmt.excluded.duration_seconds,
|
||||
"distance_meters": stmt.excluded.distance_meters,
|
||||
"computed_at": stmt.excluded.computed_at,
|
||||
},
|
||||
)
|
||||
session.execute(stmt)
|
||||
session.commit()
|
||||
|
||||
def get_distances_for_listings(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue