gendesign/backend/app/workers/tasks/developer_registry_refresh.py
bot-backend 6982255fb3
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m54s
CI / backend-tests (pull_request) Successful in 17m0s
fix(workers): убрать max_retries, который ничего не делает (#2464)
11 тасок объявляли `max_retries=2`, но ретраи не реализовывали: ни
`autoretry_for` в декораторе, ни вызова `self.retry()` в теле. Celery в
таком виде параметр не применяет — при исключении таска падает с первой
попытки. Читающий код видит «до 3 попыток», а их одна.

Убран `max_retries` у: cbr_macro_sync, rosstat_macro_sync,
developer_registry_refresh, location_refresh, mv_sales_tracker_refresh,
refresh_analytics, refresh_layout_velocity, refresh_quarter_price_index,
scrape_objective.sync_objective_group, supply_layers_refresh,
scrape_kn.scrape_kn_region. Заодно убран `bind=True` там, где `self` не
использовался вовсе; в `scrape_kn_region` он оставлен — `self.request.id`
пишется в kn_scrape_log.

Не тронуты и не должны быть: `resume_kn_run` (max_retries=12 +
настоящий self.retry()), `nspd_sync`/`scrape_cadastre` (autoretry_for),
`nspd_geo`/`objective_etl` (max_retries=0 — честное «ретраев нет»).

Гейт `test_2464_retry_config_is_real.py` разбирает AST всех модулей
`app/workers/tasks/` и требует: если декоратор объявляет ненулевой
max_retries, в нём есть autoretry_for либо в теле функции есть
self.retry(). Три таски из одиннадцати гейт нашёл сверх списка эпика.

Проверка гейта: с фиксом зелено, при возврате `max_retries=2` в
supply_layers_refresh — красно с указанием на эту таску. Плюс два
контроля: гейт видит ≥20 тасок (не молчит из-за пустой выборки) и
признаёт обе законные формы ретраев.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 17:17:38 +05:00

61 lines
3 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 task: refresh developer_registry materialized view (#1088 «GG-форсайт»).
Вызывает ``fn_refresh_developer_registry()`` (миграция 149,
``data/sql/149_developer_attribution.sql``) — REFRESH MATERIALIZED VIEW CONCURRENTLY
``developer_registry`` (реестр застройщиков по норм-ИНН: канон-имя + track-record
permits+domrf). CONCURRENTLY не блокирует SELECT-читателей (analyze) во время refresh.
Scheduled via hardcoded beat entry в workers/beat_schedule.py:
'developer-registry-refresh-monthly' — ежемесячно 1-го числа в 05:30 МСК,
через 30 мин после 'ekburg-permits-monthly' (05:00 МСК), чтобы permits-сторона
реестра обновлялась на свежих РНС/РВЭ. domrf-сторона обновляется ежедневно
(scrape_kn), но ИНН/track-record застройщиков меняются редко — monthly refresh
реестра с запасом достаточно (резолвер всё равно читает domrf-quarter напрямую).
Issue: #1088.
"""
from __future__ import annotations
import logging
from typing import Any
from sqlalchemy import text
from app.core.db import SessionLocal
from app.workers.celery_app import celery_app
logger = logging.getLogger(__name__)
# Ретраев здесь нет, и параметров, обещающих их, быть не должно (#2464). Стояло
# `bind=True, max_retries=2`, но self не использовался, self.retry() не вызывался и
# autoretry_for задан не был — конфигурация не имела эффекта. Соседи, где ретраи
# нужны, задают их явно: autoretry_for (nspd_sync, scrape_cadastre) или self.retry()
# (scrape_kn).
@celery_app.task(
name="tasks.developer_registry_refresh.refresh_developer_registry",
)
def refresh_developer_registry() -> dict[str, Any]:
"""REFRESH MATERIALIZED VIEW CONCURRENTLY developer_registry.
Лёгкая задача (реестр ~1024 застройщика). CONCURRENTLY — non-blocking для
читателей analyze; требует unique-индекс uq_developer_registry_inn (создан
миграцией 149). Возвращает row-count реестра после refresh для observability.
Returns:
dict для Celery result store / логирования.
"""
db = SessionLocal()
try:
db.execute(text("SELECT fn_refresh_developer_registry()"))
db.commit()
row = db.execute(text("SELECT COUNT(*) FROM developer_registry")).first()
count = int(row[0]) if row else 0
logger.info("refresh_developer_registry: completed, developers=%d", count)
return {"status": "ok", "developer_registry_rows": count}
except Exception as e:
logger.exception("refresh_developer_registry failed: %s", e)
raise
finally:
db.close()