gendesign/backend/app/workers/tasks/refresh_analytics.py
lekss361 f80a2c1d05 fix(scrape): SQLAlchemy text() парсил ':00:' regex как named-param
В nspd_kn.py:get_pending_cads и admin_scrape.py:nspd_coverage regex-фильтры
quarter_cad_number !~ '^00:00:' и !~ ':0000000$' падали с psycopg.errors.
DataError — двоеточие в text() трактуется как ':param'. Заменил на NOT LIKE
с bindparams (быстрее regex и без issue с парсингом).

Эффект на проде:
- /api/v1/admin/scrape/nspd/coverage возвращал 500 → теперь 200
- Кнопка «Запустить sweep» больше не дизейбленa (pending=964 теперь видно)
- Сам scraper тоже бы валился на этом же баге при beat-запуске
2026-04-30 23:16:11 +03:00

49 lines
1.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Celery tasks для регулярного refresh аналитических метрик.
Расписание задаётся в celery_app.beat_schedule. Сейчас:
- refresh_ekb_districts_medians — раз в месяц 5-го числа в 04:00 МСК
(после публикации последнего rosreestr-квартала + NSPD beat-cycle).
"""
from __future__ import annotations
import logging
from typing import Any
from app.core.db import SessionLocal
from app.services.analytics_refresh import refresh_ekb_districts_median
from app.workers.celery_app import celery_app
logger = logging.getLogger(__name__)
@celery_app.task(
bind=True,
name="tasks.refresh_analytics.refresh_ekb_districts_medians",
max_retries=2,
)
def refresh_ekb_districts_medians(
self: Any,
window_months: int = 24,
min_deals: int = 50,
) -> dict[str, Any]:
"""Refresh ekb_districts.median_price_per_m2 + mean_price_per_m2.
Лёгкая задача (1-2 секунды на 8 районов), не требует locks.
Запускается ежемесячно. Возвращает результат для аудита (что обновлено).
"""
db = SessionLocal()
try:
rows = refresh_ekb_districts_median(db, window_months=window_months, min_deals=min_deals)
logger.info("refreshed %d districts", len(rows))
return {
"updated_count": len(rows),
"districts": rows,
"window_months": window_months,
"min_deals": min_deals,
}
except Exception as e:
logger.exception("refresh_ekb_districts_medians failed: %s", e)
raise
finally:
db.close()