reindex: пересборка витрины проигрыванием журнала
- `healthlog reindex` собирает витрину из журнала (тела архива + учёт доставок) в ОТДЕЛЬНЫЙ файл базы, строго по `(received_at, id)`; рабочую базу читает без наката миграций и не трогает вовсе. Подмену делает человек при остановленном сервисе: переименование поверх открытого дескриптора портит базу молча. - Журналом считается архив, а не таблица доставок: тело без учётной записи заводится заново (метка из ULID, размер и хеш по распакованному телу), запись без тела переносится, но не сворачивается. Оракул сходимости встроен — два отпечатка и «объектов было/стало»; пустой журнал успехом не считается. - Прогон живого архива переехал на новый пакет: второго проигрывателя журнала в проекте не осталось, а его утверждение о ключе сна перестало быть константой, протухающей с каждой доставкой.
This commit is contained in:
@@ -47,3 +47,29 @@
|
||||
обязан иметь границу по `received_at` разбираемой доставки. Тест сходимости
|
||||
на живом архиве (`internal/fold/replay_test.go`) остаётся постоянным —
|
||||
именно он это поймал.
|
||||
|
||||
## 2026-08-02 — прогон живого архива был красным и об этом никто не знал
|
||||
|
||||
- **Где:** `internal/fold/replay_test.go` (перенесён в `internal/replay/archive_test.go`)
|
||||
- **Симптом:** первый же запуск `task verify:archive` в задаче про пересборку
|
||||
дал `координат sleep_analysis 222, измерено 174`. Проверено прогоном прежней
|
||||
редакции теста на том же архиве: она даёт ровно те же 222, 2049 объектов и тот
|
||||
же отпечаток — значит тест покраснел не от изменений задачи, а сам, когда
|
||||
архив дорос с 94 доставок до 116.
|
||||
- **Причина:** утверждение было пришпилено к **числу, производному от корпуса**
|
||||
(174 координаты сна). Корпус растёт с каждой доставкой, то есть константа
|
||||
протухает по расписанию телефона. Проверяемое свойство при этом другое и от
|
||||
размера корпуса не зависит: ключ по интервалу не схлопывает записи до ключа
|
||||
по метке (222 координаты против 218 меток).
|
||||
- **Почему не поймали:** прогон живого архива намеренно не входит в `task gate`
|
||||
(минута работы, данные есть только на этой машине). У проверки, которую гейт
|
||||
не гоняет, краснота никому не видна — она обнаруживается только следующей
|
||||
задачей, которая до неё дотянется. Ни один проход ревью прогон не запускал:
|
||||
проходы читают код, а не гоняют опциональные команды.
|
||||
- **Что меняем:** утверждение переписано на само свойство (координат строго
|
||||
больше, чем различных меток), измеренные числа остались в `t.Logf`. Правило
|
||||
общее и годится в конвенции: **в проверке на живом корпусе нельзя утверждать
|
||||
число, производное от размера корпуса** — утверждать надо инвариант, а число
|
||||
печатать. Гейт при этом не трогаем: цена ежедневной минуты выше цены такой
|
||||
протухшей константы, а после этой задачи прогон стал ещё и единственным, кто
|
||||
проверяет настоящий проигрыватель журнала.
|
||||
|
||||
Reference in New Issue
Block a user