0028 — Native e jar no ar, com a troca feita instância a instância¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-15 · Decidido em: 2026-09-15
Contexto¶
A casa deploya o server Micronaut como binário native por padrão, e o jar só com motivo registrado (decisão central 0033). O integrador compilava para native desde a 0020, mas rodava só jar nas seis instâncias, uma por cliente. A 0033 cita como motivo bloqueios de locale, FCM e Jackson no upload, além da falta de e2e native, e nenhum deles estava registrado aqui.
Medição de 2026-09-15: binário -Ob compilado no Windows, Postgres de dev e as mesmas 47 checagens
contra o jar e contra o native (views, estáticos, ingest XADM, upload do PowerSync, heartbeat, export
XLSX, /api/health, OpenAPI).
- Locale: o push formata moeda em pt-BR, e a GraalVM embarca só
en. O build ganhou-H:IncludeLocales=pt-BR. - Jackson no upload: o upload do PowerSync lia o corpo pelo
ObjectMapperdo Jackson, por reflexão. Passou aoJsonMapperdo Micronaut Serde, gerado em compile-time. O ingest XADM (árvore do Jackson) e o registro do/api/health(umMap) passam no binário sem metadata extra. - Paridade: 45 de 47 nos dois. As duas divergências são as mesmas no jar e no native e não vêm do
AOT:
/favicon.icofora da raiz dos estáticos, e/admin/mensageriasem cabeçalhoAccept. - Custo: boot até o
/healthem 3,6 s (native) contra 8,0 s (jar); RSS de 137 MiB contra 365 MiB. O número absoluto muda no Linux; a proporção é o que se mediu. - Fora da medição: o envio FCM real (o push fica desligado em dev), a formatação pt-BR no binário
(só o push formata), o build Linux do
Dockerfile.nativee uma suíte e2e native do integrador.
Decisão¶
Correção 2026-09-15: o reconcile do central-backend lê
int-jar.<cli>.xadm.bizcomo a mesma instância (Coolify, dois recursos no mesmo domínio), e o jar movido para esse host não perde a instância. O jar de troca fica noint.<cli>, dividindo o tráfego com o native, até a instância provar o native; depois vai para oint-jar.<cli>.xadm.biz, e o native fica dono doint.<cli>. O jar só se move quando o reconcile no ar aceita esse host; antes disso, fica noint.<cli>. Procedimento no runbook de implantação.
O build.targets passa a ["native", "jar"], e a troca é feita instância a instância.
- Cada cliente ganha o recurso
integrador-server-<cli>-native-pull, que puxa a tagnative-amd64, com o mesmo domínio da instância (int.<cli>.xadm.biz) como primeiro FQDN. O control-plane tira a instância só do primeiro FQDN e só na formaint.<cli>.xadm.biz: um jar movido para outro domínio perderia a instância e colidiria com os outros cinco no mapa de deploy. - Enquanto os dois estão no ar, o proxy divide o tráfego da instância entre jar e native. A divisão se
mede pelo
flavordo/health. - A troca começa por uma instância com o push ligado, que serve de piloto do FCM. As demais ganham o
-native-pulluma a uma, cada uma só depois de smoke verde e GlitchTip sem exceção nova na anterior. - O jar só para quando sai do
build.targets, numa release própria, depois que as seis instâncias têm native. Enquantojarestiver nobuild.targets, cada release redeploya o-jar-pull, e um recurso parado voltaria a subir. Depois dessa release, o-jar-pullfica parado como fallback.
Consequências¶
- A release builda as duas imagens, e o deploy dispara os dois alvos em todas as instâncias. Os seis
recursos
-native-pullexistem antes da primeira release com native (implantação). - A release só sai depois que o
xadm-commonspublicar as versões de lib que este app declara: oDockerfile.nativebuilda num container limpo, que resolve dependências só pelo registro. - Durante a troca há duas cópias do app no mesmo banco. Elas não duplicam efeito: o relay da
mensageria elege instância, a limpeza diária é idempotente, o backfill do manifesto é barrado pelo
UNIQUEdos itens (uma corrida no boot sai como ERROR no log, sem dado duplicado), e a deduplicação do push passou da memória de cada cópia para uma reivindicação no banco. - O que ficou fora da medição é coberto pela ordem da troca: o FCM real se prova no piloto, e o build Linux e o binário no ar se provam no primeiro deploy, pelo smoke de cada instância. A suíte e2e native do integrador fica como pendência declarada.
- Procedimento de build e diagnóstico: native-image.
Alternativas consideradas¶
- Jar nesta release e native na seguinte, depois de um piloto: preterida pelo dono. A medição já cobre os bloqueios que a 0033 citava, e a troca por instância limita o risco do que não foi medido.
- Só native, na próxima release: o FCM real e o build Linux iriam direto às seis instâncias, sem piloto e sem fallback no ar.