- рядом с воркером свёртки живёт горутина, раз в минуту разбирающая журнал
пассивным чекпойнтом; «журнал не разбирается» видно строкой владельцу, а не
только по `df`. Признак — пара чисел, а не флаг занятости: тот молчит под
удерживаемым читателем (`busy=0` при 6256 страницах и пяти перенесённых), а
при занятой блокировке отдаёт `-1` вместо ответа, и `-1 >= -1` читалось бы как
«разобрано целиком»
- каталог отвечает `304` на `If-None-Match`, не открывая снимок витрины. Метка
собрана из всего, от чего зависит ответ: версии витрины (`data_version` с
закреплённого соединения плюс поколение — значение локально для соединения и
не переживает переоткрытия), горизонта измерения и области действия ресурса.
Версия снимается до и после сборки: снятая после пометила бы устаревший снимок
свежим номером
- предел и дедлайн ответа отложены в задачу Read API точек вместе с измеренной
ценой первого запроса; попутно починен флаки-тест чужой задачи, искавший
значение точки в сыром буфере записи лога
- род метрики выводится сверкой минутного слоя с часовым: часовое значение
сходится с суммой минутных — накопительная, со средним — мгновенная, иначе
`unknown` и свёртка не предлагается вовсе. На живом архиве (123 доставки,
31 метрика) 7 накопительных, 9 мгновенных, противоречащих часов ноль
- `GET /api/v1/metrics` под токеном чтения отдаёт единицы, слои с границами и
род вместе с основанием измерения; род нигде не хранится — он функция витрины,
а витрина функция журнала, устаревать в нём нечему
- миграция 00009: покрывающий индекс, чтобы каталог отвечал по учётным колонкам,
не разжимая содержимое объектов
- Правило покрытия получило второй разряд (условный, как у точек), запрет
вырождения формы и счёт содержательных элементов ряда: скелет из скаляров и
ряд из null больше не затирают маршрут. Победитель внутри доставки стал
функцией множества версий — общим помощником с точками, — а провенанс
поднимается и при совпавшем хеше, иначе отложенная доставка возвращала витрину
к прежнему содержимому.
- Одно поле не того типа больше не уносит сущность, а пропуски видны в учётной
записи доставки (миграция 00008, NULL = «не измерялось»); каноническая форма
считается один раз и вне транзакции; откат бинаря поверх новой схемы отказывает
на старте; текст ошибки разбора не несёт значений из тела.
- Ревью кода профилем deep (девять проходов) нашло две регрессии и обе закрыты:
безусловный второй разряд запирал законный досчёт навсегда, а выбор победителя
был квадратичен по числу присланных версий одного ключа.
- Очередью служит сама таблица: доставка ждёт свёртки в статусе `pending`,
канал несёт только бит «есть работа». Переполнять нечего, падение процесса
очередь не теряет, а подбор `pending` при старте — обычный проход воркера, а
не отдельный код. Классификация исхода общая с пересборкой журнала.
- Исход разбора начал отражать доставку, а не обстоятельства: отмена и
занятость базы статус не меняют (иначе конкуренция за базу выводила бы
доставку из очереди навсегда), паника свёртки больше не валит процесс, а
учёт доставки идёт через транзакцию с повторами.
- Длинный бюджет ответа выдан маршруту приёма, а не всему серверу:
`write_timeout` в Go покрывает и чтение тела, и общий подъём снял бы защиту с
остальных маршрутов.
- 20 задач: 8 высоких, 9 средних, 3 низких; две заведены идеями — сутки при
смене часового пояса и пересекающиеся источники одной метрики
- план сведён к порядку и его обоснованию, единицы работы переехали в беклог