- беклог и план переехали в docs/tasks (38 задач, 11 целей), слаги переименованы с транслита на английские, 85 ссылок поправлены - conventions.md разобран в docs/conventions/, local-research.md — в docs/research/, review-journal.md — в docs/review.md с разделом настройки конвейера; заведены security.md, adr/ и .pm.json - шаг docs.py check добавлен в task gate; поведение в architecture.md помечено девятью маркерами долга, database.md получил настройки с числовым значением
5.4 KiB
Чем откатывать релиз после наката миграции
Секция: инфра · Хук: Решено: копия файла базы перед накатом. Страж версии схемы делает возврат бинаря отказом, а понизить схему нечем · Теги: goal:deploy, question
Решение принято владельцем 2026-08-02: вариант (2) — копия файла базы перед
накатом. Entrypoint контейнера копирует файл базы рядом до старта бинаря,
откат = подмена файла. Down-блоки миграций при этом честно называются
декорацией для локальной разработки, а не аварийным путём: ни один из них не
исполнялся ни разу. Осталось решить при взятии — сколько копий держим и где.
Задача естественно склеивается с деплоем. Ниже —
исходная постановка блокера, она же ТЗ.
Вынуто ревью кода задачи «Дозакрыть находки ревью по слиянию сущностей»
(проходы ops и negative, профиль deep).
Что именно решить
Та задача перенесла в store.Open стража версии схемы: база новее бинаря —
отказ на старте. Решение принято владельцем и здесь не пересматривается. Но у
него есть следствие, которое до сих пор нигде не было записано:
после того как новый бинарь накатил миграцию, возврат старого бинаря приёма не чинит. Он теперь отказывается стартовать, а понизить схему нечем:
- подкоманды миграции у бинаря нет (
serve,reindex,healthcheck); gooseCLI в образ не кладётся;- блоки
-- +goose Downв миграциях написаны, но ни один тест их не исполняет, и на рабочей базе они не выполнялись ни разу (DROP COLUMNв SQLite черезmodernc.org/sqliteне проверялся вовсе); restart: unless-stoppedпревращает отказ в цикл перезапуска, а телефон всё это время шлёт в закрытый порт и не перешлёт потом.
То есть аварийный путь придётся изобретать в момент аварии, при остановленном
приёме. Цена простоя для метрик закрывается широким и глубоким проходами
синхронизации; для stateOfMind не закрывается ничем — у него доставки HAE
единственный источник.
Вопросы
- Подкоманда
healthlog migrate --down-to N. Цена: новая поверхность CLI плюс тест наDownкаждой миграции (сейчас их нет, иDROP COLUMNв SQLite ведёт себя не так, как в постгресе). Зато откат становится операцией, а не импровизацией. - Копия файла базы перед накатом — entrypoint контейнера делает
cpрядом, откат = подмена файла. Цена: место (база растёт), плюс правило «сколько копий держим». Зато не требует ни кода, ни доверия кDown, а база производна от архива — потеря копии не смертельна. gooseCLI в образ. Цена: образ перестаёт быть одним статическим бинарём, появляется вторая точка, знающая про схему.- Ничего, но записать вслух: «понижение схемы не поддерживается, лечение — только выкатка вперёд». Цена: в аварии выбора нет.
Рекомендация
(2) плюс уже сделанная запись из (4). Копия файла — единственный вариант,
который не требует доверять непроверенному коду ровно в тот момент, когда
проверять некогда; а Down-блоки при этом честно называются декорацией для
локальной разработки.
Что стоит, пока решения нет
Ничего: страж работает, и это правильно. Стоит только аварийный сценарий —
он существует ровно в том виде, в каком описан выше. Строка «понижение схемы не
поддерживается» уже записана в docs/architecture.md (раздел «Деплой»).