From ebd59af05629f266a5674b9815a6693266d18e49 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sun, 2 Aug 2026 09:11:53 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B1=D0=B5=D0=BA=D0=BB=D0=BE=D0=B3:=20=D0=B4?= =?UTF-8?q?=D0=B2=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B8=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D1=80=D0=B0=D0=B7=D0=B1=D0=BE=D1=80=D0=B0=20reindex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - целостность собранной витрины проверяется отпечатком на открытом дескрипторе — перед необратимой подменой нужен integrity_check - пересборка материализует учёт и список путей архива целиком: расход памяти растёт вместе с журналом --- docs/backlog/README.md | 2 ++ docs/backlog/celostnost-pered-podmenoj.md | 27 +++++++++++++++++++ docs/backlog/pereborka-ne-vlezaet-v-pamyat.md | 26 ++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 docs/backlog/celostnost-pered-podmenoj.md create mode 100644 docs/backlog/pereborka-ne-vlezaet-v-pamyat.md 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`.