- каждая запись каталога задач получила тип вместо тега kind: и префикса заголовка; секция роадмапа «Разработка» стала «Сопровождением», порядок секций канонический - поправлены протухшие факты: нереализованные маршруты Read API, MCP и `healthlog import`, словарь слоёв в инварианте, семантика гейта по покрытию диффа, периметр перестал дублировать security.md - замер слияния переведён с находки 49 на находку 54, заполнены Purpose спек storage и parsing
47 lines
3.3 KiB
Markdown
47 lines
3.3 KiB
Markdown
# ✨ Отвечать 304 на повторный запрос точек
|
|
|
|
- **Тип:** feature
|
|
- **Категория:** Ядро
|
|
- **Зачем:** Агент опрашивает по расписанию, а каждый повтор стоит полного чтения: на каталоге это 693 мс и +153 МиБ
|
|
- **Теги:** goal:read-api, sprint:2026-08-04
|
|
|
|
Повторный опрос точек с той же меткой стоит `304` вместо полного чтения, и метка
|
|
не может ответить на другой набор данных.
|
|
|
|
Машинерия готова и берётся, а не пишется заново: `store.VersionedRead` держит
|
|
правило «версией, снятой после чтения, не подписывать», `internal/httpapi/conditional.go`
|
|
разбирает `If-None-Match` и отдаёт `304`. Новое здесь ровно одно — **область
|
|
действия метки**. У каталога ответ есть функция версии витрины; у точек он ещё и
|
|
функция параметров запроса, поэтому `etag(scope, version)` требует их
|
|
канонизированной формы. Ошибиться тут значит ответить `304` на другой набор
|
|
данных — молча и без следов.
|
|
|
|
Цена, которую это снимает, измерена на каталоге: 693 мс и +153 МиБ живой кучи на
|
|
враждебном запросе. Агент опрашивает по расписанию, и без условного запроса
|
|
каждый его повтор стоит полного чтения.
|
|
|
|
Двигает строку «Завершения» цели: «Повторный запрос тех же точек стоит `304`, а не полного чтения».
|
|
|
|
## Затрагивает
|
|
|
|
Маршрут `GET /api/v1/metrics/{name}` — заголовки `ETag` и `If-None-Match`,
|
|
код ответа `304`. Область действия метки: набор параметров запроса (метрика,
|
|
окно, слой) и версия витрины, из которых метка считается, и их каноническая
|
|
форма. Схемы и формата на диске не трогает.
|
|
|
|
## Критерии приёмки
|
|
|
|
- повторный запрос с `If-None-Match` при неизменной витрине даёт `304` — оракул:
|
|
тест
|
|
- запрос, отличающийся любым параметром по очереди (метрика, окно, слой), при
|
|
той же версии витрины даёт `200` и другое тело — оракул: тест, перебирающий
|
|
параметры по одному
|
|
- параметры, различающиеся только формой записи (порядок, регистр, эквивалентная
|
|
запись времени), дают одну и ту же метку — оракул: тест на канонизации
|
|
|
|
## Рамки
|
|
|
|
Схема не трогается, данные только читаются. Берётся после точек за период.
|
|
|
|
Связано: `docs/architecture.md` → «Условный запрос».
|