Каталог DOM.РФ в beat: вместо обещания «вернуть после cooldown» — факт о блокировке StormWall и тест, который не даст включить молча #3566

Merged
bot-backend merged 3 commits from fix/ptica-domrf-waf-probe into main 2026-09-17 09:15:51 +00:00
2 changed files with 48 additions and 8 deletions
Showing only changes of commit b2ff92afbb - Show all commits

View file

@ -346,11 +346,13 @@ def build_beat_schedule() -> dict:
# Вторник 04:00 МСК (crontab в МСК, #1233). batch 300/run → 1532 объекта
# за ~5 недель полного обновления.
#
# DISABLED 2026-05-24: DOM.РФ WAF дал hard-ban на VPS IP после серии failed
# extras-сессий (run 26/27/28). Catalog SSR использует тот же BrowserSession
# + те же /сервисы/* paths → следующий beat-tick (вт 26.05 04:00 МСК) насыпет
# 300 failed SSR fetches и углубит WAF reputation penalty. Возврат после
# cooldown 24-48h (проверить через targeted test).
# DISABLED с 2026-05-24. Исходная причина «hard-ban, cooldown 24-48h» оказалась
# догадкой: kn-прогоны 29-33 (03.06-28.06) шли успешно уже после 24.05. Зонды
# 20.08, 27.08 и 01.09 (#2443, #3307): наш.дом.рф стоит за StormWall (куки
# spid/spjs/spsc), IP Poincare получает «Доступ заблокирован [403]» — это
# блокировка, ожидание её не снимает. Каталог не собирался с 19.05.
# Включать только после решения по прокси и принятого по числу строк
# kn-прогона (#3307). Выключенность держит test_beat_schedule_domrf_catalog.py.
# schedule["scrape-kn-catalog-objects-weekly"] = {
# "task": "tasks.scrape_kn_catalog_objects.scrape_kn_catalog_objects",
# "schedule": _parse_cron("0 4 * * 2"), # вторник 04:00 МСК
@ -362,11 +364,11 @@ def build_beat_schedule() -> dict:
# (цена/статус/отделка/потолки/дата обновления) + plan-изображения квартир из
# SSR-страниц каталога. Селектит domrf_kn_flats WHERE catalog_url_hash IS NOT NULL.
#
# DISABLED (как и object-level выше): 1) тот же DOM.РФ WAF hard-ban на VPS IP —
# каталог-квартиры используют тот же BrowserSession + /сервисы/* paths.
# DISABLED (как и object-level выше): 1) та же блокировка StormWall на IP
# Poincare — каталог-квартиры используют тот же BrowserSession + /сервисы/* paths.
# 2) Sequencing: пока #2442 Task 1 (elemId → catalog_url_hash) не задеплоен и
# свежий kn-sweep не наполнил hash, SELECT вернёт 0 строк — включать смысла нет.
# Возврат после WAF-cooldown + первого kn-sweep с hash (проверить targeted-тестом).
# Включать после прокси и принятого kn-прогона с hash (#3307), не по таймеру.
# Разнести по времени с object-scrape (вт 04:00), чтобы не двоить WAF-нагрузку —
# напр. четверг 04:00 МСК.
# schedule["scrape-kn-catalog-flats-weekly"] = {

View file

@ -0,0 +1,38 @@
"""#2443: каталожные DOM.РФ-скраперы не должны попасть в beat, пока стоит блокировка.
С 01.09 наш.дом.рф за StormWall отдаёт IP Poincare «Доступ заблокирован [403]».
Решение «выключено до прокси» раньше жило только в комментарии с обещанием
«cooldown 24-48h» и месяцами читалось как таймер. Здесь оно проверяется по
значению: включить запись = осознанно поправить этот тест после #3307.
"""
from __future__ import annotations
from unittest.mock import patch
_BLOCKED_TASKS = (
"tasks.scrape_kn_catalog_objects.scrape_kn_catalog_objects",
"tasks.scrape_kn_catalog_flats.scrape_kn_catalog_flats",
)
def test_domrf_catalog_scrapers_not_scheduled_while_stormwall_blocks() -> None:
from app.workers import beat_schedule
with patch.object(beat_schedule, "_build_beat_schedule_from_db", return_value={}):
schedule = beat_schedule.build_beat_schedule()
# Контроль: статическая часть расписания реально построилась, иначе
# отсутствие задач ниже было бы зелёным по построению.
assert schedule["refresh-quarter-price-index"]["task"] == (
"tasks.refresh_quarter_price_index.refresh_quarter_price_index_chain"
)
# По task, а не по ключу: переименованный ключ не должен обойти проверку.
scheduled = {
name: entry["task"] for name, entry in schedule.items() if entry["task"] in _BLOCKED_TASKS
}
assert scheduled == {}, (
f"каталог DOM.РФ включён в beat: {scheduled}. IP Poincare заблокирован "
"StormWall (#2443); включать только после прокси и принятого kn-прогона (#3307)"
)