ADR 0209 — Engine переходит на Elixir 1.20.4 / OTP 29.1.1
Статус
Accepted. 2026-10-02 (AT-398; решение владельца от 02.10, "subir o engine para OTP 29.1.x"). Меняет runtime, зафиксированный в ADR 0024 (решение 10: одна и та же версия Elixir в Dockerfiles и в CI), не редактируя его, — правило ЕДИНСТВЕННОЙ версии продолжает действовать, меняется сама версия.
Контекст
С AT-361 Dockerfile.prod engine работает на Alpine 3.24.2 с OTP
27.3.4.18 (hexpm не публикует 27.1.2 на 3.24), тогда как dev и CI оставались на
Elixir 1.17.3 / OTP 27.1.2 / Alpine 3.20.3. Сборка engine в CI начала
обрываться примерно в 10% прогонов (0/57 до #821, 5/49 после) с:
sys_signal_stack.c:101:sys_sigaltstack(): Internal error
Измеренная причина: musl 1.2.6 из Alpine 3.24 отвергает альтернативный стек сигналов
фиксированного размера (SIGSTKSZ = 8192), который запрашивает ERTS 27, на хостах с AMX
(erlang/otp#11349). Исправление — определять размер через sysconf(_SC_MINSIGSTKSZ)
(коммиты 3a94587176/fc35c2496c) — существует ТОЛЬКО начиная с OTP 29.1. Тот же
дефект заставил бы ПРОДАКШЕН-engine умереть при загрузке на сервере с AMX:
перемежающийся сбой CI — это лотерея машин.
Откат Alpine до 3.22 решил бы симптом и заморозил бы образ на линии, которая перестаёт получать исправления безопасности; это не было выбрано.
Решение
- Engine работает на Elixir 1.20.4 / OTP 29.1.1 в dev, продакшене и CI.
Образ —
hexpm/elixir:1.20.4-erlang-29.1.1-alpine-3.24.2, закреплённый по digest ИНДЕКСА (sha256:ad851f40…, ADR 0159/0178), ОДИН И ТОТ ЖЕ в builderDockerfile.prodи вDockerfileдля dev. Продакшен-runtime остаётсяalpine:3.24.2(musl builder совпадает с musl runtime). Elixir 1.20 — единственная линия с образом и сборкой hexpm для OTP 29.1. ELIXIR_VERSION/OTP_VERSIONподнимаются вместе в трёх workflows, которые их объявляют (ci.yml,golden-set-rag.yml,golden-set-qa.yml), аmix.exsначинает требовать~> 1.20.- Job "Build, scan e smoke" печатает, есть ли у хоста AMX
(
grep -c amx_tile /proc/cpuinfo): зелёный на хосте с AMX — доказательство того, что дефект не вернулся, а не удача лотереи. - Ни одна зависимость
mix.lockне изменилась:mix deps.get+mix compile --warnings-as-errorsпроходят на новой версии. Проверщик типов Elixir 1.20 указал на мёртвую клаузулу вEngine.Agents.FilaDeMensagens.acordar/3— сбой подъёма агента БРОСАЕТСЯ, а не возвращается как значение, — и она была исправлена с локализацией ошибки по агенту, а не заглушена.
Последствия
- Цена для dev: тома
_build/depsengine были скомпилированы с OTP 27. Mix сам перекомпилирует то, что было собрано другой версией Elixir, поэтому достаточноdocker compose up -d --build engine; если том упорно держит старый артефакт,docker volume rmдля двух томов engine. Поскольку это автоматическая перекомпиляция, изменение НЕ является breaking для эксплуатирующего. - Тому, кто запускает engine вне Docker, нужен Elixir 1.20.4 / OTP 29.1.1
(
mix format --check-formattedзависит от версии, ADR 0024, решение 10). - Dependabot
docker: с OTP 29.1 + Alpine 3.24 сломанной пары больше нет, и ни одногоignoreне добавлено. Он может предложить более новый тегhexpm/elixirOTP 29.1.x — все содержат исправление. Предложение, которое ОПУСКАЕТ до OTP < 29.1 при Alpine ≥ 3.24, вновь вносит дефект и должно быть отклонено при ревью. - Rollout в Kubernetes на мгновения смешивает узлы OTP 27 и 29: распределённый Erlang допускает пары с разницей в две старшие версии.