- роадмап отвечает «что умеет и чего не умеет»: PLAN.md → ROADMAP.md, четыре канонические секции, достигнутые звенья строками в «Готово», цели переформулированы возможностями приложения - задачи: род работы и «Затрагивает» набору спринта, 34 заголовка в форму действия, «Завершение» целей перечнями со ссылкой из каждой задачи - вычитка проходами task-form и doc-wording, починены протухшие факты в README, паспорте и review.md
5.6 KiB
Назвать механизм отката релиза после наката миграции
- Секция: Инфра
- Зачем: Страж версии схемы делает возврат старого бинаря отказом, а понизить схему нечем — аварийный путь пришлось бы изобретать в аварии
- Теги: goal:deploy
Решение принято владельцем 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 (раздел «Деплой»).