[needs-human] НСПД не отдаёт данные с 27.07 — 24 суток без единого успешного дампа, WAF 403 на IP VPS #2956

Closed
opened 2026-08-20 08:02:58 +00:00 by bot-backend · 4 comments
Collaborator

Факт

Последний успешный дамп НСПД — 27.07.2026 01:06:59. Сегодня 20.08. Двадцать четыре суток источник не обновляется, и об этом нет ни одного сигнала.

Помесячно (nspd_quarter_dumps):

месяц дампов с harvest_error ЗОУИТ рисков
2026-05 154 2 940 0
2026-06 249 2 2164 0
2026-07 205 0 1831 0
2026-08 61 61 0 0

В августе ошибочны все дампы до единого. Первая ошибка — 03.08, последняя — 17.08. За последние 7 суток 25 дампов, все пустые.

Тексты ошибок:

61 × TimeoutError: The read operation timed out
 4 × NspdLiteError: HTTP 500: <?xml ... ServiceExceptionReport ...

Что происходит прямо сейчас

Проба рабочим трактом — тот же NSPDClient, тот же метод, что и в harvest, изнутри gendesign-backend-1, 20.08 08:00 UTC:

risk_flooding                id=872205   NspdBulkWafError: HTTP 403 WAF block
risk_flooding_underground    id=872202   NspdBulkWafError: HTTP 403 WAF block
risk_swampification          id=872203   NspdBulkWafError: HTTP 403 WAF block
zouit_engineering (контроль) id=37578    NspdBulkWafError: HTTP 403 WAF block
<h1>Forbidden</h1>
Client IP: 46.173.16.127
Rule: 57615a88d1ec0120b56fdce6

Блокируется всё, включая контрольный слой, который в июле исправно отдавал данные. То есть это не «сломался слой», а закрыт доступ с адреса VPS. Похоже на тот же класс, что #2443 (DOM.РФ WAF hard-ban на этот же IP).

Читать TimeoutError в августовских дампах стоит с осторожностью: WAF, держащий соединение, даёт ровно такую картину. Утверждать, что это одна и та же причина, у меня оснований нет — только совпадение окна.

Чем это оплачивается

Через search_by_quarter идут ВСЕ слои НСПД, не только риски: parcels, buildings, territorial_zones, red_lines, engineering_structures, пять слоёв ЗОУИТ, пять слоёв возможностей и одиннадцать риск-слоёв. То есть на паузе весь §6 отчёта и всё, что строится на тер-зонах квартала.

Отдельно стоит сказать, чего НЕ произошло: отчёт не врёт. При harvest_error != NULL код (#1371) отдаёт dump_available=False и перезапускает harvest, а make_empty_result ставит risks_count: None с прямым комментарием «ноль означал бы „спросили и не нашли“». Честная деградация работает. Проблема в том, что перезапуск harvest'а тут же падает снова, и так 24 дня.

Почему никто не узнал

Дампы продолжают писаться (строка есть, счётчики нулевые, harvest_error заполнен), расписание отрабатывает, красного в CI нет. События harvest_quarter error в GlitchTip есть — но уведомлений он не шлёт вообще, см. #2673: за всю историю ноль правил и ноль отправок.

Что нужно от владельца

Разблокировка адреса VPS у НСПД либо решение о прокси — как и в #2443. Кодом это не чинится, поэтому не берусь.

Что можно сделать кодом (отдельно от разблокировки)

Сторож свежести: max(fetched_at_utc) WHERE harvest_error IS NULL старше N суток → громкий сигнал. Сейчас единственный признак — что кто-то руками посмотрит в таблицу. Двадцать четыре дня показывают, что этого не происходит.

Критерий приёмки

Появился хотя бы один дамп с harvest_error IS NULL и total_features > 0 позже 20.08.2026.

## Факт **Последний успешный дамп НСПД — 27.07.2026 01:06:59.** Сегодня 20.08. Двадцать четыре суток источник не обновляется, и об этом нет ни одного сигнала. Помесячно (`nspd_quarter_dumps`): | месяц | дампов | с `harvest_error` | ЗОУИТ | рисков | |---|---|---|---|---| | 2026-05 | 154 | 2 | 940 | 0 | | 2026-06 | 249 | 2 | 2164 | 0 | | 2026-07 | 205 | 0 | 1831 | 0 | | **2026-08** | **61** | **61** | **0** | **0** | В августе ошибочны **все** дампы до единого. Первая ошибка — 03.08, последняя — 17.08. За последние 7 суток 25 дампов, все пустые. Тексты ошибок: ``` 61 × TimeoutError: The read operation timed out 4 × NspdLiteError: HTTP 500: <?xml ... ServiceExceptionReport ... ``` ## Что происходит прямо сейчас Проба рабочим трактом — тот же `NSPDClient`, тот же метод, что и в harvest, изнутри `gendesign-backend-1`, 20.08 08:00 UTC: ``` risk_flooding id=872205 NspdBulkWafError: HTTP 403 WAF block risk_flooding_underground id=872202 NspdBulkWafError: HTTP 403 WAF block risk_swampification id=872203 NspdBulkWafError: HTTP 403 WAF block zouit_engineering (контроль) id=37578 NspdBulkWafError: HTTP 403 WAF block ``` ``` <h1>Forbidden</h1> Client IP: 46.173.16.127 Rule: 57615a88d1ec0120b56fdce6 ``` Блокируется **всё**, включая контрольный слой, который в июле исправно отдавал данные. То есть это не «сломался слой», а закрыт доступ с адреса VPS. Похоже на тот же класс, что #2443 (DOM.РФ WAF hard-ban на этот же IP). Читать `TimeoutError` в августовских дампах стоит с осторожностью: WAF, держащий соединение, даёт ровно такую картину. Утверждать, что это одна и та же причина, у меня оснований нет — только совпадение окна. ## Чем это оплачивается Через `search_by_quarter` идут ВСЕ слои НСПД, не только риски: `parcels`, `buildings`, `territorial_zones`, `red_lines`, `engineering_structures`, пять слоёв ЗОУИТ, пять слоёв возможностей и одиннадцать риск-слоёв. То есть на паузе весь §6 отчёта и всё, что строится на тер-зонах квартала. Отдельно стоит сказать, чего НЕ произошло: отчёт не врёт. При `harvest_error != NULL` код (#1371) отдаёт `dump_available=False` и перезапускает harvest, а `make_empty_result` ставит `risks_count: None` с прямым комментарием «ноль означал бы „спросили и не нашли“». Честная деградация работает. Проблема в том, что перезапуск harvest'а тут же падает снова, и так 24 дня. ## Почему никто не узнал Дампы продолжают писаться (строка есть, счётчики нулевые, `harvest_error` заполнен), расписание отрабатывает, красного в CI нет. События `harvest_quarter error` в GlitchTip есть — но уведомлений он не шлёт вообще, см. #2673: за всю историю ноль правил и ноль отправок. ## Что нужно от владельца Разблокировка адреса VPS у НСПД либо решение о прокси — как и в #2443. Кодом это не чинится, поэтому не берусь. ## Что можно сделать кодом (отдельно от разблокировки) Сторож свежести: `max(fetched_at_utc) WHERE harvest_error IS NULL` старше N суток → громкий сигнал. Сейчас единственный признак — что кто-то руками посмотрит в таблицу. Двадцать четыре дня показывают, что этого не происходит. ## Критерий приёмки Появился хотя бы один дамп с `harvest_error IS NULL` и `total_features > 0` позже 20.08.2026.
Author
Collaborator

Насколько это срочно — цифры, а не тревога

Отказ идёт с 27.07, но кэш дампов держит удар. Померил, чтобы issue не преувеличивал.

Кого уже задело

analysis_runs, поле result->'nspd_dump'->>'available':

период разборов дамп есть дампа нет поля нет
до 27.07 3993 1969 (49 %) 58 (1.5 %) 1966
после 27.07 101 45 (45 %) 6 (6 %) 50

Доля «дамп есть» почти не изменилась: 49 % → 45 %. Отказ бьёт только по кварталам, для которых дампа ещё не было — их за три недели набралось шесть.

Когда станет хуже

_DUMP_MAX_AGE_DAYS = 180 (quarter_dump_lookup.py:35) — кэш живёт полгода.

успешных дампов          603
самый старый             2026-05-17
самый свежий             2026-07-27
первое истечение         2026-11-13

До 13.11 старые дампы считаются годными и отдаются как есть. После этой даты они начнут уходить на перезагрузку, которая падает, и «дампа нет» пойдёт вверх уже по всем кварталам, а не только по новым.

Что это меняет

Пожар не сегодняшний: сегодняшняя цена — шесть разборов из 101 и остановка обновления данных. Но окно на решение конечно и заканчивается 13.11.2026. Формулирую как срок, а не как «когда-нибудь»: после него ухудшение перестаёт быть постепенным.

Отдельно стоит помнить, что 603 дампа — это снимок, которому уже месяц-три: даже пока «дамп есть», содержимое устаревает, а обновиться не может.

## Насколько это срочно — цифры, а не тревога Отказ идёт с 27.07, но кэш дампов держит удар. Померил, чтобы issue не преувеличивал. ### Кого уже задело `analysis_runs`, поле `result->'nspd_dump'->>'available'`: | период | разборов | дамп есть | дампа нет | поля нет | |---|---|---|---|---| | до 27.07 | 3993 | 1969 (49 %) | 58 (1.5 %) | 1966 | | после 27.07 | 101 | 45 (45 %) | **6 (6 %)** | 50 | Доля «дамп есть» почти не изменилась: 49 % → 45 %. Отказ бьёт только по кварталам, для которых дампа ещё не было — их за три недели набралось шесть. ### Когда станет хуже `_DUMP_MAX_AGE_DAYS = 180` (`quarter_dump_lookup.py:35`) — кэш живёт полгода. ``` успешных дампов 603 самый старый 2026-05-17 самый свежий 2026-07-27 первое истечение 2026-11-13 ``` До 13.11 старые дампы считаются годными и отдаются как есть. После этой даты они начнут уходить на перезагрузку, которая падает, и «дампа нет» пойдёт вверх уже по всем кварталам, а не только по новым. ### Что это меняет Пожар не сегодняшний: сегодняшняя цена — шесть разборов из 101 и остановка обновления данных. Но окно на решение конечно и заканчивается 13.11.2026. Формулирую как срок, а не как «когда-нибудь»: после него ухудшение перестаёт быть постепенным. Отдельно стоит помнить, что 603 дампа — это снимок, которому уже месяц-три: даже пока «дамп есть», содержимое устаревает, а обновиться не может.
Author
Collaborator

Прод-проверка сторожа: до и после #2957

Один и тот же замер (compute_freshness изнутри gendesign-backend-1), деплой между ними.

до правки после
nspd.status ok stale
nspd.age_days 3.32 24.32
nspd.last_success_at 2026-08-17 01:02 — упавший дамп 2026-07-27 01:06 — последний успешный
gisogd_permits ok, 9.21 ok, 9.21

gisogd_permits здесь контроль: правка не должна была его тронуть, и не тронула.

stale входит в _ALERTABLE beat-таски scrape_freshness_check, так что теперь по этому источнику пойдёт сообщение в GlitchTip.

Оговорка, чтобы не выдать половину дела за целое: уведомлений GlitchTip по-прежнему никому не шлёт — за всю историю ноль правил и ноль отправок (#2673). Сторож перестал врать, но чтобы кто-то узнал, нужен ещё адресат. Это решение владельца.

Сам отказ НСПД остаётся: код починил только слепоту монитора.

## Прод-проверка сторожа: до и после #2957 Один и тот же замер (`compute_freshness` изнутри `gendesign-backend-1`), деплой между ними. | | до правки | после | |---|---|---| | `nspd.status` | `ok` | **`stale`** | | `nspd.age_days` | 3.32 | **24.32** | | `nspd.last_success_at` | 2026-08-17 01:02 — упавший дамп | **2026-07-27 01:06** — последний успешный | | `gisogd_permits` | `ok`, 9.21 | `ok`, 9.21 | `gisogd_permits` здесь контроль: правка не должна была его тронуть, и не тронула. `stale` входит в `_ALERTABLE` beat-таски `scrape_freshness_check`, так что теперь по этому источнику пойдёт сообщение в GlitchTip. Оговорка, чтобы не выдать половину дела за целое: **уведомлений GlitchTip по-прежнему никому не шлёт** — за всю историю ноль правил и ноль отправок (#2673). Сторож перестал врать, но чтобы кто-то узнал, нужен ещё адресат. Это решение владельца. Сам отказ НСПД остаётся: код починил только слепоту монитора.
Author
Collaborator

Блокировка снята. Причина была ровно та, что зафиксирована в теле тикета — адрес.

В теле стоит ответ WAF:

Client IP: 46.173.16.127
Rule: 57615a88d1ec0120b56fdce6

Это адрес старого хоста. 25-26.08 продукт переехал, 27.08 владелец обновил адреса; сегодня site-finder ходит с 188.124.37.140.

Проба тем же трактом

Тот же NSPDBulkClient, тот же метод search_by_quarter, изнутри gendesign-backend-1 — то есть буквально то, чем ходит harvest:

квартал 66:41:0704002 -> ОК, объектов: 86
квартал 66:41:0303161 -> ОК, объектов: 117

Ни одного NspdBulkWafError. Для сравнения: 20.08 тем же трактом блокировалось всё, включая контрольный слой.

Уточнение по формулировке тикета

«Последний успешный дамп 27.07» относится к nspd_quarter_dumps. Отдельно от него живут задания nspd_geo_jobs — они on-demand, последнее (job_id=66, одиночный кадастровый номер) отработало 04.07 со статусом done и нулём блокировок. То есть механика заданий не ломалась, встал именно квартальный harvest.

Смежное: cad_parcels — 42 234 строки, максимум 04.07, за 30 суток ноль новых.

Что осталось сделать

Доступ вернулся сам собой вместе со сменой адреса — правки кода задача не требует. Осталось перезапустить сбор и убедиться, что квартальные дампы снова наполняются, а не только что одиночный запрос проходит.

Отдельно стоит заметить на будущее: сигнала об этом отказе не было ни одного — 24 суток тишины при полностью остановленном источнике. Это ровно то, о чём #3078; там теперь есть доставка алертов, но правила на «источник молчит N суток» среди 16 существующих нет.

**Блокировка снята. Причина была ровно та, что зафиксирована в теле тикета — адрес.** В теле стоит ответ WAF: ``` Client IP: 46.173.16.127 Rule: 57615a88d1ec0120b56fdce6 ``` Это адрес старого хоста. 25-26.08 продукт переехал, 27.08 владелец обновил адреса; сегодня site-finder ходит с `188.124.37.140`. ## Проба тем же трактом Тот же `NSPDBulkClient`, тот же метод `search_by_quarter`, изнутри `gendesign-backend-1` — то есть буквально то, чем ходит harvest: ``` квартал 66:41:0704002 -> ОК, объектов: 86 квартал 66:41:0303161 -> ОК, объектов: 117 ``` Ни одного `NspdBulkWafError`. Для сравнения: 20.08 тем же трактом блокировалось всё, включая контрольный слой. ## Уточнение по формулировке тикета «Последний успешный дамп 27.07» относится к `nspd_quarter_dumps`. Отдельно от него живут задания `nspd_geo_jobs` — они **on-demand**, последнее (`job_id=66`, одиночный кадастровый номер) отработало 04.07 со статусом `done` и нулём блокировок. То есть механика заданий не ломалась, встал именно квартальный harvest. Смежное: `cad_parcels` — 42 234 строки, максимум **04.07**, за 30 суток ноль новых. ## Что осталось сделать Доступ вернулся сам собой вместе со сменой адреса — правки кода задача не требует. Осталось перезапустить сбор и убедиться, что квартальные дампы снова наполняются, а не только что одиночный запрос проходит. Отдельно стоит заметить на будущее: сигнала об этом отказе не было ни одного — 24 суток тишины при полностью остановленном источнике. Это ровно то, о чём #3078; там теперь есть доставка алертов, но правила на «источник молчит N суток» среди 16 существующих нет.
Author
Collaborator

Сбор восстановлен. Доказано сквозным прогоном, а не только пробой клиента.

Квартал 66:01:0202002 прогнан штатной машинерией (harvest_quarter.apply_asyncgendesign-worker-1, kwargs как у beat):

было (24.08) стало (27.08 21:54)
total_features 0 25
parcels_count 0 1
territorial_zones_count 0 6
zouit_count 0 14
harvest_error TimeoutError: The read operation timed out NULL

Соседние кварталы того же тика 24.08 (66:01:2301009, 66:01:0701001) по-прежнему лежат с TimeoutError — контраст виден в одной выборке.

Задача отработала за 68,6 с, обошла все 26 слоёв (parcels, buildings, тер-зоны, красные линии, ЗОУИТ×5, риски×11, opportunity×5). Ни одного таймаута, ни одного NspdBulkWafError.

Августовские таймауты объяснены

В теле стояла осторожная формулировка: «WAF, держащий соединение, даёт ровно такую картину, но утверждать, что это одна причина, оснований нет». Теперь основания есть: 26 последовательных запросов на том же квартале, тем же кодом, с той же машины — ни одного таймаута. Изменился только IP. Все 61 августовская ошибка — тот же блок.

Чинить нечего

Правки кода задача не потребовала: доступ вернулся вместе со сменой адреса. Включать тоже нечего — квартальный harvest не заведён в job_settings, он живёт расписанием в коде (backend/app/workers/beat_schedule.py:464-469, понедельник 04:00 МСК) плюс ленивым триггером при генерации отчёта (services/site_finder/quarter_dump_lookup.py:219,283-291). Beat при этом всё время работал исправно — строки с ошибками проштампованы 24.08 01:01-01:02 UTC, то есть ровно понедельничным тиком, который упирался в блок.

Ближайший тик (понедельник) добьёт 80 ошибочных дампов сам: сортировка ORDER BY cad_number, 66:01:* идут первыми, при batch_size=50 это два тика.

Отдельно вынесено

Общий бэклог покрытия — 669 дампов на 11 048 кварталов — темпом расписания не догоняется. Это не следствие блокировки и было верно и до неё; вынес отдельным тикетом.

Закрываю.

**Сбор восстановлен. Доказано сквозным прогоном, а не только пробой клиента.** Квартал `66:01:0202002` прогнан штатной машинерией (`harvest_quarter.apply_async` → `gendesign-worker-1`, kwargs как у beat): | | было (24.08) | стало (27.08 21:54) | |---|---|---| | `total_features` | 0 | **25** | | `parcels_count` | 0 | 1 | | `territorial_zones_count` | 0 | 6 | | `zouit_count` | 0 | 14 | | `harvest_error` | `TimeoutError: The read operation timed out` | **NULL** | Соседние кварталы того же тика 24.08 (`66:01:2301009`, `66:01:0701001`) по-прежнему лежат с `TimeoutError` — контраст виден в одной выборке. Задача отработала за 68,6 с, обошла все 26 слоёв (parcels, buildings, тер-зоны, красные линии, ЗОУИТ×5, риски×11, opportunity×5). **Ни одного таймаута, ни одного `NspdBulkWafError`.** ## Августовские таймауты объяснены В теле стояла осторожная формулировка: «WAF, держащий соединение, даёт ровно такую картину, но утверждать, что это одна причина, оснований нет». Теперь основания есть: 26 последовательных запросов на том же квартале, тем же кодом, с той же машины — ни одного таймаута. Изменился только IP. Все 61 августовская ошибка — тот же блок. ## Чинить нечего Правки кода задача не потребовала: доступ вернулся вместе со сменой адреса. Включать тоже нечего — квартальный harvest не заведён в `job_settings`, он живёт расписанием в коде (`backend/app/workers/beat_schedule.py:464-469`, понедельник 04:00 МСК) плюс ленивым триггером при генерации отчёта (`services/site_finder/quarter_dump_lookup.py:219,283-291`). Beat при этом всё время работал исправно — строки с ошибками проштампованы 24.08 01:01-01:02 UTC, то есть ровно понедельничным тиком, который упирался в блок. Ближайший тик (понедельник) добьёт 80 ошибочных дампов сам: сортировка `ORDER BY cad_number`, `66:01:*` идут первыми, при `batch_size=50` это два тика. ## Отдельно вынесено Общий бэклог покрытия — 669 дампов на 11 048 кварталов — темпом расписания не догоняется. Это не следствие блокировки и было верно и до неё; вынес отдельным тикетом. Закрываю.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2956
No description provided.