Повторный анализ кодовой базы (docs/reviews/2026-09-26-codebase-review-2.md) и доработки:
025 Ёмкость префикса — размер его подсети (а не сумма листьев); «Обзор» считает ёмкость
по корневым активным IPv4-префиксам и адреса внутри них.
026 Политика блокировки входа: 5 неудач на логин+IP, 20 на IP, 50 на логин со всех IP,
кроме известных IP (known_logins, миграция 0009) — владельца нельзя заблокировать анонимно.
027 Сериализация попыток входа по IP (advisory-lock после блокировки логина).
028 UI «Префиксы»: загрузка всех страниц (до 20 000), счётчики по total, предупреждение об усечении.
029 Advisory-lock по VRF для операций, меняющих дерево префиксов и раскладку адресов.
030 Исправление замечаний ревью 025-029: _lock_prefix (VRF блокируется до чтения префикса,
409 при одновременном переносе), константы политики входа перенесены в app/services.py.
Тесты: 14 passed (проверка ёмкости родителя приведена к семантике 025); сквозные сценарии
и гонки — docs/reviews/2026-09-26-changes-025-029-review.md, 2026-09-27-changes-030-review.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
Ревью и тестирование изменения 030 — 2026-09-27
Объём: правки агента (Sonnet 5) по плану docs/changes/030-review-fixes-025-029/PLAN.md, которые закрывают замечания 1 и 2 ревью 2026-09-26-changes-025-029-review.md.
Изменены app/api/v1/prefixes.py, app/api/v1/auth.py, app/services.py, app/rotation.py.
Тестировались только доработки 1 и 2. Помимо этого выполнен регрессионный прогон pytest.
Ревью кода
Замечание 1 — _lock_prefix
Хелпер работает в таком порядке:
SELECT vrf_idпрефикса;_lock_vrfдля этого VRF и дополнительных (целевого VRF при переносе), одним вызовом, по возрастанию id;- повторное чтение префикса под
FOR UPDATEсpopulate_existing; - если
vrf_idк этому моменту изменился — 409 без повтора.
Хелпер применён в delete_prefix, update_prefix (только при смене VRF), create_address, allocate_subnet, allocate_next.
- Порядок блокировок единый: везде сначала advisory-блокировка VRF, затем строка префикса.
update_prefixбез смены VRF блокирует только строку (при flush) и не запрашивает блокировку VRF, поэтому цикла ожидания нет. - Отказ от повтора обоснован. Повтор оставил бы в транзакции блокировку устаревшего VRF и нарушил бы возрастающий порядок захвата между попытками. Сценарий 1d показал, что ветка 409 реально срабатывает.
- Встречные переносы (A: 5→3, B: 3→5) блокируют пару VRF одним вызовом в одинаковом порядке, взаимной блокировки нет. Подтверждено сценарием 1c.
- Побочный эффект:
create_addressтеперь берётFOR UPDATEстроки префикса, и назначения адресов в одном префиксе выполняются по одному. На нагрузку это не влияет, операции короткие.
Замечание 2 — константы входа
LOGIN_WINDOW,MAX_PER_LOGIN_IP,MAX_PER_IP,MAX_PER_LOGIN,KNOWN_IP_DAYSперенесены вapp/services.py.auth.pyиrotation.pyимпортируют их оттуда. Пространства ключей advisory-блокировок остались вauth.py.- Импорт
app.rotationбольше не загружает модулиapp.api.*: проверено поsys.modules, список пуст. Докстрингauth.pyформатируется корректно.
Новых замечаний нет.
Тесты
| Проверка | Результат |
|---|---|
Стенд ipam_control_006 пересобран, app healthy |
✅ |
Регрессия pytest -q |
✅ 14 passed |
2: app.rotation не импортирует API-слой |
✅ |
2: политика входа не изменилась: 5 неудач → 401×4 + 429, на верный пароль тоже 429, Retry-After ≈ 600 с |
✅ |
| 1a: удаление префикса ∥ вставка промежуточного префикса, ×20 | ✅ все пары ответов 204/201; дерево согласовано: у каждого префикса родитель — самый узкий охватывающий |
| 1b: перенос в другой VRF ∥ создание адреса в переносимом префиксе, ×20 | ✅ без 500 и взаимных блокировок; у всех адресов vrf_id совпадает с VRF их префикса; все 20 префиксов перенесены |
| 1c: встречные переносы двух префиксов между двумя VRF, ×15 | ✅ всё 200/200, взаимных блокировок нет |
| 1d: перенос ∥ удаление того же префикса, ×10 | ✅ только ожидаемые исходы: 5× (перенос 200, удаление 409 «одновременно изменяется»), 5× (перенос 404, удаление 204) |
Лог приложения: deadlock / Traceback |
✅ 0 |
Сценарии выполнялись скриптом во временной папке, в репозиторий он не добавлен. Временные данные (vt30-*), попытки входа и записи known_logins удалены.
Вывод
Замечания 1 и 2 закрыты. Изменения 025–030 готовы к коммиту.