Files
healthlog/docs/backlog/read-api-tochki.md
T
av 03edf1087d Каталог разрезов и измеренный род агрегации
- род метрики выводится сверкой минутного слоя с часовым: часовое значение
  сходится с суммой минутных — накопительная, со средним — мгновенная, иначе
  `unknown` и свёртка не предлагается вовсе. На живом архиве (123 доставки,
  31 метрика) 7 накопительных, 9 мгновенных, противоречащих часов ноль
- `GET /api/v1/metrics` под токеном чтения отдаёт единицы, слои с границами и
  род вместе с основанием измерения; род нигде не хранится — он функция витрины,
  а витрина функция журнала, устаревать в нём нечему
- миграция 00009: покрывающий индекс, чтобы каталог отвечал по учётным колонкам,
  не разжимая содержимое объектов
2026-08-02 19:23:59 +03:00

62 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Read API: точки, выбор слоя, свёртка по сетке
**Приоритет:** высокий
Сейчас данные достаются только `sqlite3` на хосте. Все три сценария —
агент-медик, трекер тренировок, фитнес-игра — упираются в отсутствие чтения.
Формы запроса ровно две, и это один запрос с необязательным параметром:
`?from&to` — все значения за период (вес, лекарства, симптомы), `?from&to&bucket`
— с разбивкой (шаги, энергия).
Решение по размеру ответа (вариант «б»): разбивка не задана и ответ не влезает —
сервер сам берёт сетку погрубее и **называет её в ответе**; разбивка задана явно
и не влезает — ошибка со списком доступных сеток, а не тихая подмена. Различие
существенно: иначе агент, попросивший минутную сетку, получит суточные суммы.
**Отдача тренировок и записей входит сюда же.** Разбор и хранение сущностей с
собственным `id` сделаны (change `2026-08-02-trenirovki-i-zapisi`), а эндпоинтов
нет: тренировка с маршрутом и записи `stateOfMind` лежат в витрине и наружу не
отдаются. Вводить их раньше конверта ответа значило бы задать контракт
мимоходом, поэтому `GET /workouts`, `GET /workouts/{id}` и
`GET /records/{kind}` закрываются этой задачей — вместе с формой конверта и
правилом размера ответа. Второй сценарий паспорта (трекер) до тех пор не закрыт.
Готово, когда «шаги за неделю по дням» и «вес за год» отвечаются одним запросом
каждый, тренировка отдаётся одним пакетом вместе с маршрутом, а в ответе всегда
видно `layer`, `bucket` и `aggregation`.
**Порог неполного ведра решается здесь, и вместе с ним — его полярность.**
Каталог и род агрегации сделаны (change `2026-08-02-katalog-i-rod-agregacii`), и
измерению порог заполненности не понадобился: у него две конкурирующие гипотезы,
и неполный час не сходится ни с одной сам собой. Свёртке в ответе он нужен, а
готовые решения задают его **противоположно**: Graphite `xFilesFactor` — доля
обязательно известных точек (умолчание 0.5 при роллапе и 0 при рендере, один
параметр с двумя умолчаниями), RRDtool `xff` — доля допустимо неизвестных. Обе
величины выглядят как «0.5», означая разное; полярность придётся назвать вслух в
`architecture.md`, иначе через полгода два места кода поймут поле по-разному.
**Предел размера ответа тоже здесь.** У каталога его нет намеренно: правило
размера — общее для маршрутов чтения, и задавать его мимоходом на первой ручке
значило бы решить контракт до того, как известна форма тяжёлого ответа. Каталог
станет первым его потребителем.
**Форма провода наследуется от каталога, и это надо решить один раз.** Сегодня
типы `internal/catalog` сами несут json-теги, а транспорт владеет только
обёрткой: переименование поля в домене меняет публичный контракт без касания
`httpapi`. Держит это один байтовый тест непустого ответа. Либо объявить в
`architecture.md`, что типы чтения и есть форма провода для всех транспортов
(HTTP и MCP отдают её байт в байт), либо завести DTO в транспорте — но выбрать до
того, как образец скопирует эта задача.
**Клиент обязан смотреть на границы окна измерения.** Род метрики измерен по
48 самым свежим ОБЩИМ часам, а не по последним 48 часам календаря: если минутная
автоматизация HAE выключена, множество общих часов не пополняется и окно
замирает. Род при этом продолжает объявляться, и единственный след — `last_hour`
в ответе. Правило выбора свёртки в Read API обязано это учитывать (или явно
объявить, что не учитывает).
Связано: `docs/architecture.md` → «Read API», «Измерение рода агрегации»,
план → шаг «Read API».