diff --git a/backend/app/services/site_finder/market_metrics.py b/backend/app/services/site_finder/market_metrics.py index 20f32a8f..77b11863 100644 --- a/backend/app/services/site_finder/market_metrics.py +++ b/backend/app/services/site_finder/market_metrics.py @@ -810,6 +810,9 @@ _OFFER_TREND_SQL = text( # Границы вменяемости цены предложения (руб/м²). Шире, чем сделки-тренд (30k–500k): # предложение включает премиум/апартаменты; отсекаем только явный ETL-мусор. +# ⚠ Значения зеркалированы ЛИТЕРАЛАМИ в partial-предикате покрывающего индекса +# data/sql/186_objective_lots_history_offer_trend_covering_idx.sql — при изменении +# констант индекс надо пересоздать, иначе offer-trend молча теряет Index-Only Scan. _OFFER_PRICE_MIN: int = 10000 _OFFER_PRICE_MAX: int = 1000000 @@ -875,12 +878,16 @@ def compute_offer_price_trend( } try: rows = db.execute(_OFFER_TREND_SQL, params).mappings().all() - except Exception: - logger.exception( - "market_metrics: offer-trend query failed (lat=%s lon=%s radius=%s)", + except Exception as exc: + # Ожидаемый путь: 8с-гвард (parcels.py) отменяет запрос на холодном кэше + # (~2/сутки, профилирование 2026-07-04) — блок аддитивный, analyze успешен. + # WARNING, не exception: ERROR-уровень поднимал ложные GlitchTip-события. + logger.warning( + "market_metrics: offer-trend query failed (lat=%s lon=%s radius=%s): %s", center_lat, center_lon, radius_m, + exc, ) rows = []