tasks: закрыт разбор и хранилище, начат спринт по чтению данных клиентами
- цель parsing-and-storage закрыта по своему критерию; незакрываемый остаток (новые формы от источника, ручные секции задним числом) переехал в тему parsing-completeness - цель mcp поглощена целью read-api, переименованной в «Чтение данных клиентами»: адаптер — последний шаг того же направления, а не своё - read-api-points разложена на конверт с точками, свёртку по сетке и тренировки с записями; спринт 2026-08-04 набран пятью задачами
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# Конверт ответа и точки за период
|
||||
|
||||
- **Секция:** ядро
|
||||
- **Зачем:** Точки лежат в витрине и наружу не отдаются: ни один потребитель не может спросить «вес за год» иначе как sqlite3 на хосте
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
Потребитель получает значения метрики за период одним запросом
|
||||
`?from&to`, и из ответа видно, что именно ему отдали: слой, род свёртки и
|
||||
границу окна, в котором род измерен.
|
||||
|
||||
Первая из трёх частей, на которые разложена `read-api-points`. Здесь решается
|
||||
**конверт** — форма, которую унаследуют все остальные маршруты чтения и оба
|
||||
транспорта.
|
||||
|
||||
**Форма провода решается здесь, один раз.** Сегодня типы `internal/catalog`
|
||||
сами несут json-теги, а транспорт владеет только обёрткой: переименование поля
|
||||
в домене меняет публичный контракт без касания `httpapi`, и держит это один
|
||||
байтовый тест непустого ответа. Либо объявить в `architecture.md`, что типы
|
||||
чтения и есть форма провода для всех транспортов (HTTP и MCP отдают её байт в
|
||||
байт), либо завести DTO в транспорте. Выбрать надо **до** того, как образец
|
||||
скопируют соседние задачи.
|
||||
|
||||
**Машинерия условного запроса готова — её берут, а не пишут заново.**
|
||||
`store.VersionedRead` держит правило «версией, снятой после чтения, не
|
||||
подписывать»; `httpapi` умеет `If-None-Match` и `304`. Новое здесь одно: метка
|
||||
обязана нести **область действия** — у точек ответ есть функция параметров
|
||||
запроса, поэтому `etag(scope, version)` требует их канонизированной формы, иначе
|
||||
`304` ответит на другой набор данных. Детали — `docs/architecture.md`,
|
||||
«Условный запрос».
|
||||
|
||||
**Клиент обязан видеть границы окна измерения.** Род метрики измерен по 48 самым
|
||||
свежим **общим** часам, а не по последним 48 часам календаря: выключенная
|
||||
минутная автоматизация HAE останавливает пополнение множества общих часов, и
|
||||
окно замирает, продолжая объявлять род. Единственный след — `last_hour` в
|
||||
ответе; конверт обязан его нести.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- «вес за год» отвечается одним запросом без доступа к файлу базы — оракул:
|
||||
запрос к поднятому сервису на живом архиве
|
||||
- в ответе всегда видны `layer`, `aggregation` и `last_hour` — оракул: тест на
|
||||
форме ответа
|
||||
- повторный запрос с `If-None-Match` даёт `304`, а тот же запрос с другими
|
||||
параметрами — `200` с другим телом — оракул: тест на паре запросов с разной
|
||||
областью действия метки
|
||||
- форма провода объявлена в `docs/architecture.md` — доменные типы или DTO, —
|
||||
и соседние маршруты ссылаются на это решение, а не повторяют выбор — оракул:
|
||||
глазами по разделу
|
||||
|
||||
## Рамки
|
||||
|
||||
Схема не трогается, данные только читаются, сервис перезапускается. Против
|
||||
`./data` — только `task up` / `task run`.
|
||||
|
||||
Связано: `docs/architecture.md` → «Read API», «Условный запрос», «Измерение рода
|
||||
агрегации».
|
||||
Reference in New Issue
Block a user