Job state is changed under one RLock, the Dockerfile copies all root modules and imports them at build time, RIPEstat requests go through a retrying session with the sourceapp parameter (ripestat_sourceapp) and a capped Retry-After. Adds the summary and marks review findings 5-10 fixed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5.2 KiB
5.2 KiB
Итоги: исправления 5-10 по результатам ревью
План: docs/plan-review-fixes-5-10.md. Источник: docs/review-2026-09-21.md. Два этапа, два коммита; тестов стало 27 (было 24).
Этап А: путь чтения (находки 5, 6, 10), коммит d6b69d0
- 5. Один снимок в
/addresses:db.read_transaction, одна сессия вместо трёх; курсор вX-Changes-Cursorберётся в том же снимке, что и данные. Функцииget_cidrs/get_fqdn_ipsудалены. - 6.
/healthбез путей: вlast_restoreтолько{at, backup}(имя файла копии); каталоги, карантин и текст ошибки остаются вlast_restore.json. - 10.
get_changesпакетами: проверка наличия порциями поPRESENCE_BATCH = 500вместо запроса на каждое значение;get_changesиспользуетread_transaction. - Проверка: ответы шести запросов (
/addressesс разными параметрами,/addresses/diff) до и после совпали побайтно;get_changes(cursor=0)на журнале из 12 тыс. записей: 6832 мс -> 88 мс; при параллельной записи пар ASN/FQDN старый код дал 303 несогласованных ответа из 411, новый - 0 из 601.
Этап Б: демон, образ, внешний источник (находки 7, 8, 9)
- 7. Состояние заданий:
_state_lockсталRLock, все измененияjob_state(run_job,schedule_jobs,sync_schedule) выполняются под ним; при прерывании (SystemExit) прежняяlast_errorсохраняется. - 8.
Dockerfile:COPY *.py ./вместо списка модулей и проверкаimport api_server, collector_daemon, db, healthcheckна этапе сборки. - 9. RIPEstat: сессия
requestsс повторами (до 3, при сбоях соединения и кодах 429/500/502/503/504, паузы 0, 2, 4 с), параметрsourceapp(по умолчаниюripe-cidr-collector, ключripestat_sourceappвconfig.json), сессия создаётся на запуск сбора и закрывается в конце. После исчерпания повторов источник пропускается, ничего не удаляется. - Тесты: 2 новых (задание
backupв демоне: регистрация, ротация поbackup_keep; сессия RIPEstat:sourceapp, ключ из конфига,Noneпосле сбоя, настройка повторов и потолкаRetry-After). - README:
ripestat_sourceapp, логика повторов, проверка образа.
Проверка этапа Б
- Локальный «RIPEstat»: два ответа 503, затем 200 -> результат за 2,0 с, три запроса, в каждом
sourceapp(значение из конфига); постоянный 429 сRetry-After: 3600(потолок на время проверки 1 с) -> 4 попытки за 3,0 с, источник пропущен с записью в лог. - Сборка образа: текущий код собирается; копия проекта без
formatters.pyне собирается (падает импорт); новый модуль в корне попадает в образ без правкиDockerfile. - Docker Compose (отдельный проект, порт 18000, стенд убран): три задания в
/health, ручной сбор FQDN отработал, расписаниеbackupизменено через API и применено демоном (копия появилась),status: ok, сервисыhealthy, ошибок в логе нет. - Первая попытка негативной проверки образа не выполнилась (в среде нет
rsync): повторена черезtar.
Отличия от плана и замечания
- Паузы 0, 2, 4 с, а не 1, 2, 4: первая повторная попытка в
urllib3идёт без паузы. Худший случай на один ASN около 46 с (4 попытки по 10 с и паузы). Retry-Afterне «уважается» безусловно, а ограничен потолкомMAX_RETRY_AFTER = 30с: иначе ответ сRetry-After: 3600блокировал бы сборщик на час. В худшем случае с длиннымRetry-Afterодин ASN займёт до 130 с.sourceappвиден RIPE: не помещайте в него секреты; контакт администратора допустим.- Оставлено: архитектурные замечания ревью (вынос путей в
settings.py, разделениеapi_server.pyиcidr_collector.py), ограничение частотыPOST /collect, повторные запросы DNS.