непокрытые секции доставки видны в статусе разбора
- половина потока (50 доставок из 104) не несёт metrics вовсе и до сих пор числилась parsed: ретеншен, поверив статусу, срезал бы тела stateOfMind, которых в экспорте Apple нет - разбор перечисляет верхнеуровневые ключи data, непокрытые проглатываются декодированием: тело 40 МиБ из непокрытой секции удерживает 0 МиБ - статус partial и колонка delivery.uncovered_sections; миграция переводит прежние parsed в pending — им верить нельзя - витрина не изменилась: отпечаток совпал с прогоном до изменения
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
## Why
|
||||
|
||||
Разбор читает только `data.metrics`. Доставка, целиком состоящая из другой
|
||||
секции, получает `parse_status=parsed` с нулём точек — неотличимо от доставки с
|
||||
пустой секцией метрик. Измерено на живом архиве: из 99 доставок 48 не содержат
|
||||
`metrics` вовсе (24 `workouts`, 24 `stateOfMind`), то есть почти половина потока
|
||||
сейчас числится разобранной, не будучи разобранной.
|
||||
|
||||
Само по себе это некритично — тела лежат в архиве. Опасность в сцепке с
|
||||
ретеншеном: он по замыслу срезает архив до следующего проверенного экспорта, и
|
||||
если станет опираться на `parse_status`, снесёт тела, которые числятся
|
||||
разобранными. Для `stateOfMind` это необратимо — в экспорте Apple его нет
|
||||
(находка 46), доставки HAE единственный его источник. Ретеншен — следующая
|
||||
задача, поэтому признак нужен до неё.
|
||||
|
||||
## What Changes
|
||||
|
||||
- `hae.Parse` перечисляет верхнеуровневые ключи `data` и возвращает те, что
|
||||
разбор не покрыл. Перечисление идёт **без чтения содержимого секций**: тела
|
||||
доходят до 42 МиБ, и удержание кучи здесь — часть контракта.
|
||||
- Появляется статус доставки `partial` рядом с `parsed`/`failed`: тело
|
||||
разобрано в той части, которую разбор покрывает, и в нём остались
|
||||
непокрытые секции.
|
||||
- Свёртка сохраняет список непокрытых ключей в исход доставки и называет их
|
||||
**именами ключей** в своём единственном логирующем чекпоинте. Содержимого
|
||||
секций в логе нет и быть не может.
|
||||
- Число ключей и длина имени в записи ограничены: ключи приходят из тела,
|
||||
которым отправитель управляет целиком; усечение видно счётчиком и маркером.
|
||||
- **Миграция переписывает `parse_status` у всех накопленных доставок:**
|
||||
существующие `parsed` становятся `pending` — «этим разбором ещё не смотрели».
|
||||
Статус, поставленный кодом, который частичного разбора не различал, ничего не
|
||||
доказывает, а ретеншен собирается на него опираться. Цена: 99 строк живой базы
|
||||
меняют статус на первом старте нового бинаря, и до появления подбора `pending`
|
||||
(задача `otvet-i-svyortka`) никто их не пересвернёт; тела при этом остаются в
|
||||
архиве, объекты витрины — на месте, и `Down` прежние статусы не восстановит.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
Новых нет.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `parsing`: разбор обязан перечислять непокрытые верхнеуровневые ключи `data`,
|
||||
не читая их содержимого, и отдавать их вызывающему.
|
||||
- `storage`: у доставки появляется статус `partial` и список непокрытых секций;
|
||||
учёт обязан отличать «разобрано целиком» от «разобрано частично».
|
||||
|
||||
## Impact
|
||||
|
||||
- `internal/hae` — перечисление ключей в том же проходе, что и разбор метрик.
|
||||
- `internal/store` — константа статуса, колонка `uncovered_sections`, миграция.
|
||||
- `internal/fold` — исход свёртки, статус и атрибут лога.
|
||||
- `docs/database.md`, `docs/architecture.md`, `docs/local-research.md` —
|
||||
схема, статусы и находка о наборах секций в живом потоке.
|
||||
- Ретеншен сырого архива (задача `retenshen-syrogo-arhiva`) получает признак,
|
||||
на который ему можно опираться.
|
||||
Reference in New Issue
Block a user