- половина потока (50 доставок из 104) не несёт metrics вовсе и до сих пор числилась parsed: ретеншен, поверив статусу, срезал бы тела stateOfMind, которых в экспорте Apple нет - разбор перечисляет верхнеуровневые ключи data, непокрытые проглатываются декодированием: тело 40 МиБ из непокрытой секции удерживает 0 МиБ - статус partial и колонка delivery.uncovered_sections; миграция переводит прежние parsed в pending — им верить нельзя - витрина не изменилась: отпечаток совпал с прогоном до изменения
7.0 KiB
7.0 KiB
1. Разбор: перечисление непокрытых ключей
- 1.1
decodeMetrics→decodeEnvelope: одинjson.Decoderидёт по верхнему уровню, имя члена читаетсяToken(), значение покрытого ключа декодируется на месте, значение непокрытого проглатывается декодированием в выбрасываемыйjson.RawMessage(ограничитель вложенности stdlib при этом работает, в отличие от ручного счёта глубины) - 1.2 Покрытость — функция рядом с разбором, а не изменяемая пакетная карта;
Result.Uncoveredотдаёт непокрытые отсортированными и без повторов - 1.3 Границы: не больше 32 имён (
Result.UncoveredDroppedсчитает отброшенные), имя длиннее 64 байт декодированного имени обрезано по границе рун, маркер…приписывается сверх предела - 1.4 Повтор ключа
metricsдаёт объединение секций; повтор непокрытого ключа даёт одно имя. Тело безdata,dataне объект,dataпустой,metricsневерного типа — прежнее поведение (ошибка ровно там, где была) - 1.5 Ошибка после разобранной секции
metricsточек не отдаёт
2. Хранилище: статус и список
- 2.1 Константа
store.ParsePartial; док-комментарийParsePendingпереписан на «этим разбором ещё не смотрели» - 2.2 Миграция: колонка
uncovered_sections TEXT NOT NULL DEFAULT '[]'и перевод существующихparsedвpending; в комментарии миграции сказано, что по данным она односторонняя —Downснимает колонку, прежние статусы не восстанавливает - 2.3 Исход разбора пишется структурой (
store.ParseOutcome), а не растущим списком позиционных параметров; список замещает прежнее значение целиком, включая замещение пустым;nilи пустой срез записываются как[]
3. Свёртка: исход и лог
- 3.1
Stats.UncoveredиStats.UncoveredDropped; статусpartialпри непустом списке,failedсильнее; при отказе список сохраняется, если разбор успел его собрать - 3.2 Атрибуты
uncovered(структурным[]string) иuncovered_droppedв единственном логирующем чекпоинте; уровень из-за одной лишь частичности не растёт, срабатывание границ даётWARN
4. Тесты (приёмочные критерии)
- 4.1 Фикстура
uncovered_sections.json: точки метрик сохранены, ключиworkoutsиstateOfMindв списке, статусpartial - 4.2 Доставка из одной непокрытой секции: разбор без ошибки, ноль точек,
ключ в списке, статус
partial - 4.3 Доставка из одних метрик: список пуст, статус
parsed - 4.4 Детерминизм: тот же набор секций в разном порядке и с повтором ключа даёт тот же список
- 4.5 Границы: 40 ключей → 32 имени и счётчик отброшенных; длинное имя → обрезка с маркером
- 4.6 Удержание кучи: тело в десятки мегабайт, состоящее преимущественно из непокрытой секции, удерживает не больше четырёх тел; тело из вложенных скобок отвергается, а не съедает память
- 4.7 Отказ всё или ничего: тело оборвано после секции метрик — ошибка, ноль
точек,
failed - 4.8 Лог свёртки: имена ключей есть, содержимого секций нет; уровень при обычной частичности не повышен
- 4.9 Миграция: строка со статусом
parsedстановитсяpending, колонка получает[] - 4.10 Пересвёртка: доставка
partial, у которой список опустел, становитсяparsedс пустым списком - 4.11 Прогон живого архива (
task verify:archive): доставки без метрик получаютpartialс непустым списком, повторный прогон состояния не меняет - 4.12 Сверка с состоянием ДО изменения: витрина, собранная из живого архива новым кодом, совпадает по объектам, точкам и метрикам со снимком, снятым до изменения
5. Документация
- 5.1
docs/database.md: колонка, полный набор статусов, новый смыслpending - 5.2
docs/architecture.md: частичный разбор в разделе приёма - 5.3
docs/local-research.md: находка о наборах секций в живом потоке (99 доставок: 51metrics, 24workouts, 24stateOfMind, секции не смешиваются, пустых нет)
6. Замеры после реализации
- 6.1 Живой архив (104 доставки): частично разобрано 50 — 25
stateOfMindи 25workouts. Отпечаток витриныa59b38ea…совпал с прогоном ДО изменения на том же архиве: переписанный разбор конверта — строгий no-op для витрины - 6.2 Удержание кучи: тело 40 МиБ, из которых почти всё — непокрытая секция, удерживает 0 МиБ; тело из 100 000 уровней вложенности отвергается
- 6.3 Живой сервис разобрал пришедшие с телефона доставки (5 штук) —
заодно закрыт пункт 6.3a задачи
razbor-metrik-v-obekty