Files

24 lines
3.9 KiB
Markdown
Raw Permalink Normal View History

2026-09-21 07:29:38 +03:00
# Итоги: `GET /addresses/diff?since=`
План: `docs/plan-diff-endpoint.md`.
## Сделано
- **Журнал изменений** (`db.py`): таблицы `changes` и `meta`, схема версии 2. Запись ведут SQL-триггеры на `addresses`, поэтому охвачены сбор, TTL, `purge` и снятие источника. Значение попадает в журнал, только если оно появилось или исчезло в итоговом наборе (адрес, который держит другой источник, не считается удалённым). Импорт из JSON в журнал не пишется. База версии 1 обновляется автоматически при первом открытии.
- **`get_changes()`**: в одной read-транзакции берёт первое действие по значению после точки отсчёта и сверяет с текущим состоянием, поэтому удалённое и возвращённое в тот же интервал в результат не попадает.
- **Срок хранения** (`cidr_collector.py`): `changes_retention_days` (по умолчанию 30, `0` - без очистки), очистка внутри транзакции обоих сборов; граница («горизонт») хранится в `meta`.
- **API** (`api_server.py`): `GET /addresses/diff?since=<курсор | время>&type=&ip_version=` с ответом `{since, now, cursor, added, removed}`; `400` при неверном `since`, `410` при выходе за горизонт или чужом курсоре. В ответы `/addresses` добавлен заголовок `X-Changes-Cursor` (курсор читается до данных) для первой синхронизации.
- **README**: описание эндпоинта, ключа `changes_retention_days`, журнала в разделе о хранении.
- **Тесты**: 2 новых (журнал и очистка в БД; API), всего 18, в контейнере 18 passed.
## Проверка
Вручную на копии базы версии 1: миграция сохранила данные, в журнале после неё пусто; при сборе истёкший по TTL префикс попал в `removed`, новый - в `added`; время с часовым поясом (`+03:00`) разобрано.
## Отличия от плана
- Курсор рекомендован вместо времени: номер записи не зависит от часов и от длительности транзакции сборщика (иначе запись, зафиксированная позже, могла бы получить метку времени раньше выданного `now` и потеряться).
- Добавлен заголовок `X-Changes-Cursor` (в плане не было), чтобы клиент мог согласованно начать синхронизацию.
## Замечания
- Diff считается отдельно по типам (`asn`, `fqdn`); одинаковая строка в обоих типах при `type=all` сообщалась бы дважды - на практике не встречается (CIDR и IP различаются записью).
- Только JSON и без агрегации: агрегированный diff не аддитивен.
- Журнал растёт с числом изменений; при 30 днях хранения и редких изменениях RIPE объём мал. На реальных данных не проверялось (наблюдение 1 анализа остаётся в силе).
- Уведомления (webhook, Telegram) не сделаны: следующий шаг поверх журнала.