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

5.1 KiB
Raw Blame History

Why

Read API обязан уметь сворачивать метрику к запрошенной сетке, а род свёртки (сумма или среднее) HAE не присылает: Avg/Min/Max есть только у heart_rate, всё остальное приходит в qty (находка 40), заголовок доставки про род молчит, а единицы врут на краях. Просуммировать мгновенную метрику или сложить нижний слой HAE значит завысить ответ втрое — поэтому род измеряется до Read API, а не угадывается внутри него.

Второй пробел того же размера: потребитель не может спросить «что у тебя вообще есть». Слои и их диапазоны — часть контракта (после пересборки старый период законно теряет верхние слои), и узнать их сегодня можно только через sqlite на хосте.

What Changes

  • Род агрегации измеряется сверкой минутного и часового слоёв между собой: часовое значение сходится с суммой минутных — метрика накопительная, с арифметическим средним — мгновенная, ни с тем ни с другим или свидетельства противоречат — unknown. Измерено на живом архиве (123 доставки, 31 метрика): 17 метрик классифицируются, 14 остаются unknown, противоречивых свидетельств ноль.
  • Нижний слой (raw) в измерении не участвует и не суммируется никогда — он посекундная развёртка, а не сэмплы (находка 34).
  • Новая ручка GET /api/v1/metrics — каталог: по каждой метрике единицы, измеренный род с основанием измерения и список слоёв с диапазонами и числом точек. Первый маршрут под токеном чтения; появляется проверка этого токена.
  • Род нигде не хранится: он производен от витрины и считается на запрос по ограниченному окну. Ни новой колонки, ни строки в перечне того, что не переносит пересборка.
  • Схема получает только индекс (00009): разрезы и границы обязаны отвечать, не разжимая содержимое объектов. Само измерение содержимое читает — иначе сумму минутных значений не получить, — но не больше 2 × 48 объектов на метрику и одной транзакцией чтения на весь ответ.
  • Тай-брейк при равной полноте точек в этой задаче не меняется — вынут блокером: род измеряется из витрины, а витрина есть результат слияния, и правило слияния, читающее собственную выдачу, повторяет дефект вывода слоя из журнала ревью.

Capabilities

New Capabilities

  • catalog: каталог разрезов и измеренный род агрегации — что за метрики есть, в каких слоях, за какие периоды и какая свёртка по ним осмысленна.

Modified Capabilities

  • storage: каталог отвечает по учётным полям объекта, не разжимая payload; отсюда требование к стоимости выборки разрезов.

Impact

  • Новый пакет internal/catalog — измерение рода и сборка каталога.
  • internal/store — выборка разрезов метрики и общих часов двух слоёв.
  • internal/hae — единственное место, знающее, какое поле точки несёт число.
  • internal/httpapi — маршрут каталога и проверка токена чтения.
  • internal/store/migrations/00009_bucket_catalog.sql — покрывающий индекс.
  • Документация: architecture.md (метод измерения и отвергнутые чужие решения), database.md (индекс), local-research.md (находка о результате измерения), config.example.toml (read_tokens перестали быть заделом на будущее).