0011 — Habilitar GraalVM native-image no tradutor¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-11 · Decidido em: 2026-08-20
Contexto¶
A casa adotou native-image como default dos servers Micronaut elegíveis (decisão 0022 do
central): RSS ~3× menor e arranque quase instantâneo. O webstorm-ecom deployava só como imagem
JVM (eclipse-temurin, java -jar app.jar). Esta decisão habilita o native no lado-app —
o que o repositório precisa para o build native ficar verde e a imagem bootar. Padrão provado:
piloto bi-transporte-xls e central-backend (ambos native-verde na casa).
Falha de native é só em runtime (reflection/resource/serde sem metadata AOT) — "compila verde" não prova nada; o boot da imagem native é que prova.
Decisão¶
Habilitação pura, sem tocar domínio (tradutor / ingestão / mensageria). Quatro peças:
- Perfil no
build.gradle.kts—configure<GraalVMExtension>(o accessorgraalvmNative {}não é gerado no Kotlin DSL porque o pluginorg.graalvm.buildtools.nativevem transitivo doio.micronaut.application):-PnativeQuick→-Ob(loop dev/e2e, build ~40-60% mais rápido); sem a flag (prod) →-Os(imagem menor); sempre--gc=serial(menor footprint; default CE explícito). CE 25 não tem--pgo/--emit build-report/--gc=G1(Oracle-only). - Um reflect-config —
io.sentry.logback.SentryAppender, emsrc/main/resources/META-INF/native-image/br.com.xadm/webstorm-ecom/reflect-config.json(nome como string, não.class— evita o javac arrastarorg.jetbrains.annotations.Nullableausente). Ologback.xmldeclara esse appender; o Joran o instancia por reflexão → sem o registro o boot native quebra noLoggerFactory. É o único metadata manual necessário (igual ao piloto e ao central-backend); AWS SDK v2, Flyway e serde são cobertos por reachability-metadata + features do Micronaut. TODO-casa: mover a hint paraxadm-comum-web(dona doSentryInitializer) e propagar — some daqui quando a lib absorver.Atualização 2026-09-11 — cumprido. A
xadm-comum-web0.9.1 embarca a hint no próprio jar, com três entradas (SentryAppendereSentryOptionscom construtor eallPublicMethods, eLevel.valueOf); o arquivo local saiu no bump. A cópia daqui registrava só a classe: no native o logback não achava os setters e ignorava o<options>, e os eventos chegavam ao GlitchTip sem oenvironment. - Build via
dockerBuildNativedo plugin — que gera o Dockerfile native internamente. Não se escreve Dockerfile native à mão e não se adota o templatedockerfile-java-native(opcional): o piloto não usa, e divergir do fluxo provado só adiciona risco. O Dockerfile JVM atual fica intacto (prod segue JVM até o rollout, que é de operação). As tasks native do plugin não são configuration-cache-safe → invocar com--no-configuration-cache. UsardockerBuildNative, nãonativeCompile(o native é Linux;nativeCompilenum host Windows/Mac geraria binário da plataforma errada) — pré-requisito: daemon Docker. - Liveness =
/healthplano da lib — nada a implementar. O management health fica desligado (endpoints.health.enabled: false, como hoje) e o/health{status,versao}doHealthControllerdaxadm-comum-webserve de liveness. Registrado como não-decisão para não ser reaberto: reabilitar o management health recriaria a rota/healthdupla (controller incondicional da lib + management) →400em toda request (Norma 2, constituição 0.31.2).
Verificação (gate lado-app)¶
./gradlew checkverde (a config native não altera o build/testes JVM — regressão zero).dockerBuildNative -PnativeQuick --no-configuration-cachecompila a imagem native.- Boot smoke (Testcontainers
GenericContainerda imagem native + Postgres com o DDL emprestadoestoquededb/migration-test): afirma boot + Flyway(webstorm_ecom_*) +GET /health200. É boot-level, segregado do./gradlew check(exige a imagem native pré-buildada).
"Native build verde aqui" ≠ "app native funciona". O boot smoke prova o grafo de DI + logback/Sentry + serde no boot — não exercita os caminhos native-arriscados de runtime do tradutor: a query data-jdbc
EstoqueRepository.pendentes()(réplica) e o PUT real S3→Garage da ingestão. Essa prova é do e2e native, que vive em outro repo (etc/tests/native/e2e-thoms-webstorm-ecom, derivado doe2e-central-backend). O CI (ci.yml) permanece JVM; o gate native é out-of-band, coerente com o estágio protótipo native da casa.
Notas¶
awssdkreal = 2.44.7 (axadm-comum-storage:0.2.0eleva o BOM2.28.16declarado nobuild.gradle.kts) — se o e2e achar gap de reflexão no S3, procurar metadata da 2.44.x.
Alternativas descartadas¶
dockerfile-java-native(template da toolchain) — o piloto não usa; adotá-lo diverge do fluxo provado sem ganho.@Livenessexplícito + management health ligado — mais código e recria a rota/healthdupla (400). O/healthda lib já é o liveness.- Provar S3/data-jdbc no boot smoke local — exigiria Garage + poke no compose deste repo; a spec
manteve o e2e ponta-a-ponta no
etc/tests(uma fonte, não duas).
Linhagem de trabalho: .ia/013-native-image-*.