diff --git a/docs/backlog/README.md b/docs/backlog/README.md index ff1ad99..742c405 100644 --- a/docs/backlog/README.md +++ b/docs/backlog/README.md @@ -33,6 +33,7 @@ - [Импорт родного экспорта Apple Health](import-eksporta-apple.md) — Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут - [Проверка секций, которых поток ещё не приносил](proverka-novyh-sekcij.md) — Симптомы, ЭКГ, лекарства, цикл и вес не виденны живьём — разбор писался вслепую - [Наблюдаемость: /stats](stats-nablyudaemost.md) — Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах +- [Проверка целостности собранной витрины перед подменой](celostnost-pered-podmenoj.md) — Подмена файла необратима, а годность выхода подтверждена отпечатком на ещё открытом дескрипторе - [Деплой на rivendell](deploy-rivendell.md) — Сервис живёт на рабочей машине — телефон достаёт до него только дома - [Управление токенами и секретами](upravlenie-sekretami.md) — Проверка токенов выключена, config.docker.toml коммитится — так нельзя выезжать наружу - [[idea] Что считать сутками при смене часового пояса](sutki-i-chasovoj-poyas.md) — Шаги за день — базовый запрос трекера и игры, но чей это день при перелёте, не решено @@ -45,6 +46,7 @@ ## низкий - [Устаревание нижнего слоя после экспорта](ustarevanie-nizhnego-sloya.md) — Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен - [Ретеншен сырого архива](retenshen-syrogo-arhiva.md) — Архив не подчищается вовсе — 14-дневный срок объявлен, но не работает +- [Пересборка держит весь журнал в памяти](pereborka-ne-vlezaet-v-pamyat.md) — Учёт доставок и список путей архива материализуются целиком: расход растёт вместе с журналом, а у журнала конца нет - [Активный алерт «данных нет N часов»](alert-tishina-potoka.md) — Пропажу потока сейчас замечает человек, а не сервис - [[idea] Порог sealed: с какого возраста час считается запечатанным](porog-sealed.md) — WARN на изменение старого часа уже пишется, но порог не выбран — ставим по факту, когда накопится статистика досчёта - [[idea] Месячный проход по ручным секциям](mesyachnyj-prohod-ruchnye-sekcii.md) — Симптомы и лекарства заводятся задним числом на недели — недельного глубокого прохода им не хватит diff --git a/docs/backlog/celostnost-pered-podmenoj.md b/docs/backlog/celostnost-pered-podmenoj.md new file mode 100644 index 0000000..a9bd13b --- /dev/null +++ b/docs/backlog/celostnost-pered-podmenoj.md @@ -0,0 +1,27 @@ +# Проверка целостности собранной витрины перед подменой + +**Приоритет:** средний + +`healthlog reindex` собирает витрину в отдельный файл и снимает с него +отпечаток, а подмену делает человек: остановить сервис, переименовать файл, +поднять обратно. Это **единственный необратимый шаг** всей операции — и +единственный, перед которым мы ничего не проверяем. + +Отпечаток сегодня снимается на **ещё открытом дескрипторе**: он говорит, что +свёртка сошлась, но не говорит, что файл на диске корректен как база SQLite. +Между «свёртка сошлась» и «файл цел» помещается всё, о чём предупреждает +[How To Corrupt An SQLite Database](https://www.sqlite.org/howtocorrupt.html): +оборванный `fsync`, полный диск, ФС, соврала о записи. Человек в этот момент +уже удалил рабочую витрину. + +Что делать: после закрытия файла и **до** того, как команда объявит результат +годным к подмене, открыть его заново и прогнать `PRAGMA integrity_check`. +Не прошёл — команда завершается отказом и прямо говорит, что подменять нечем. + +Дёшево: одна страница кода, один прогон по готовому файлу. Ценно ровно в тот +момент, когда всё остальное уже пошло не так. + +Готово, когда `reindex` на заведомо испорченном выходном файле отказывается +называть результат годным, а на здоровом — не замедляется заметно. + +Связано: `cmd/healthlog/reindex.go`, `docs/architecture.md` → «Пересборка». diff --git a/docs/backlog/pereborka-ne-vlezaet-v-pamyat.md b/docs/backlog/pereborka-ne-vlezaet-v-pamyat.md new file mode 100644 index 0000000..264aa5e --- /dev/null +++ b/docs/backlog/pereborka-ne-vlezaet-v-pamyat.md @@ -0,0 +1,26 @@ +# Пересборка держит весь журнал в памяти + +**Приоритет:** низкий + +`healthlog reindex` материализует целиком две вещи: учёт доставок из базы и +список путей архива. На сегодняшнем объёме (сотня тел) это незаметно, на +квартальном (~12 тысяч) — терпимо, а дальше растёт линейно и без предела: +журнал по определению не подчищается до следующего проверенного экспорта. + +Отдельно к этому примешивается **размер заголовков**: `MaxHeaderBytes` у +сервера не задан, то есть верхней границы у колонки `delivery.headers` нет +вовсе. Раздутый заголовок множится на число доставок. + +Порог, за которым это перестаёт быть теорией, не измерен — с него и стоит +начинать, если задача берётся. Лечится потоковым перечислением журнала +(курсор по учёту, обход каталога партиями по суткам) вместо двух срезов в +памяти. + +Сегодня недостижимо, поэтому приоритет низкий. Естественно склеивается с +[ретеншеном сырого архива](retenshen-syrogo-arhiva.md): та задача задаёт, где +у журнала конец, эта — как его читать, не поднимая целиком. + +Готово, когда пересборка на журнале в десятки тысяч доставок идёт с потреблением +памяти, не зависящим от его длины. + +Связано: `internal/replay`, `cmd/healthlog/reindex.go`.