непокрытые секции доставки видны в статусе разбора
- половина потока (50 доставок из 104) не несёт metrics вовсе и до сих пор числилась parsed: ретеншен, поверив статусу, срезал бы тела stateOfMind, которых в экспорте Apple нет - разбор перечисляет верхнеуровневые ключи data, непокрытые проглатываются декодированием: тело 40 МиБ из непокрытой секции удерживает 0 МиБ - статус partial и колонка delivery.uncovered_sections; миграция переводит прежние parsed в pending — им верить нельзя - витрина не изменилась: отпечаток совпал с прогоном до изменения
This commit is contained in:
@@ -234,6 +234,36 @@ HRV); у накопительных — только `date`. Поэтому то
|
||||
безопасности, исход разбора виден в логе, в `delivery.parse_status` и в
|
||||
`/stats`, а доразобрать их можно командой `reindex`.
|
||||
|
||||
#### Частичный разбор
|
||||
|
||||
Разбор покрывает секцию `metrics`; `workouts`, `stateOfMind`, `symptoms`, `ecg`
|
||||
и прочие проходят мимо. Это половина потока: 48 доставок из 99 не несут
|
||||
`metrics` вовсе (находка 50).
|
||||
|
||||
Такая доставка получает статус `partial`, а имена непокрытых секций — колонку
|
||||
`delivery.uncovered_sections`. Статус отвечает на вопрос «разобрано ли всё»,
|
||||
список — «что именно осталось»; спрашивать полагается статус. Без этого
|
||||
различения `parsed` означал бы «разобрано» и для доставки, из которой не
|
||||
прочитано ни байта, а ретеншен, поверив ему, срезал бы тело — необратимо для
|
||||
`stateOfMind`, которого в экспорте Apple нет.
|
||||
|
||||
Перечисление идёт **в том же проходе**, что и разбор метрик: значение
|
||||
непокрытой секции проглатывается декодированием в выбрасываемый `RawMessage`,
|
||||
поэтому копия одна, живёт до следующего члена и удерживается ноль (измерено:
|
||||
тело 40 МиБ, из которых почти всё — непокрытая секция, удерживает 0 МиБ).
|
||||
Пропуск ручным счётом глубины по токенам этого не даёт: делимитеры идут мимо
|
||||
сканера, ограничитель вложенности `encoding/json` не работает, и тело из
|
||||
вложенных скобок съедает память вместо отказа.
|
||||
|
||||
`partial` — не отклонение, а установившееся состояние, поэтому уровень лога от
|
||||
него не растёт. Постоянный `WARN` каждые пять минут обесценил бы уровень.
|
||||
|
||||
**Правило для будущих задач: покрыли секцию — пересверните.** Список это снимок
|
||||
покрытия на момент свёртки; доставки, свёрнутые до того, как секция стала
|
||||
покрытой, останутся `partial` со старым списком, и ретеншен будет вечно щадить
|
||||
ненужные тела. Задача, которая начинает разбирать секцию, тем же изменением
|
||||
переводит `partial`-строки с этим ключом в `pending`.
|
||||
|
||||
- **413** — тело больше допустимого. Граница стоит на **распакованном**
|
||||
потоке, а не только на сжатом: `MaxBytesReader` поверх `r.Body` ограничивает
|
||||
то, что приехало по сети, а в память попадает то, что из этого развернулось.
|
||||
|
||||
Reference in New Issue
Block a user