Collector daemon, FastAPI server (addresses, diff, collect, sources), SQLite storage with change journal, Docker Compose deployment, tests, documentation and project rules. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
25 lines
3.9 KiB
Markdown
25 lines
3.9 KiB
Markdown
# Итоги: `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) не сделаны: следующий шаг поверх журнала.
|