<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cesar Schutz</title><description>O que eu estudo virando artigo — arquitetura, código, Java, IA e o que mais aparecer. Blog de Cesar Schutz, arquiteto de soluções.</description><link>https://blog.cesarschutz.com.br/</link><language>pt-BR</language><atom:link href="https://blog.cesarschutz.com.br/rss.xml" rel="self" type="application/rss+xml"/><item><title>Criptografia em repouso e em trânsito — o que é e como ativar no Postgres e no MongoDB</title><link>https://blog.cesarschutz.com.br/posts/criptografia-em-repouso-e-em-transito/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/criptografia-em-repouso-e-em-transito/</guid><description>De onde vem o termo, o que cada tipo protege (e o que não protege) e como ativar no RDS, no Postgres autogerenciado, no MongoDB Atlas e no MongoDB fora do Atlas.</description><pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Outro dia, revisando a documentação de infraestrutura de um banco, encontrei esta linha sobre uma réplica de leitura:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Criptografada em repouso com KMS (&lt;code&gt;StorageEncrypted=true&lt;/code&gt;), como a primária.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;É o tipo de frase que aparece em todo documento de arquitetura, checklist de auditoria e questionário de segurança. Todo mundo marca “sim” e segue em frente. Mas vale entender o que ela garante, &lt;span class=&quot;caneta caneta-duplo&quot;&gt;o que ela &lt;strong&gt;não&lt;/strong&gt; garante&lt;/span&gt; e qual é a irmã dela, a criptografia em trânsito.&lt;/p&gt;
&lt;p&gt;Neste post vou passar pelos dois conceitos e mostrar como ativar cada um no &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://www.postgresql.org/docs/current/encryption-options.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;PostgreSQL&lt;/span&gt; (no RDS e fora dele) e no &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://www.mongodb.com/docs/manual/core/security-encryption-at-rest/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;MongoDB&lt;/span&gt; (no Atlas e fora dele). No final, falo rapidamente de um terceiro tipo, bem menos comum: a criptografia em uso.&lt;/p&gt;
&lt;h2 id=&quot;de-onde-vem-o-termo&quot;&gt;De onde vem o termo&lt;/h2&gt;
&lt;p&gt;“Criptografia em repouso” é a tradução literal de &lt;em&gt;encryption at rest&lt;/em&gt;. Em segurança da informação, é comum separar o dado em três estados, porque cada um tem riscos diferentes e pede proteções diferentes:&lt;/p&gt;





























&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Estado, Em inglês, Onde o dado está, Proteção típica&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Estado&lt;/th&gt;&lt;th&gt;Em inglês&lt;/th&gt;&lt;th&gt;Onde o dado está&lt;/th&gt;&lt;th&gt;Proteção típica&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Em repouso&lt;/td&gt;&lt;td&gt;&lt;em&gt;at rest&lt;/em&gt;&lt;/td&gt;&lt;td&gt;Parado no disco, no backup, no snapshot&lt;/td&gt;&lt;td&gt;Criptografia de disco, TDE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Em trânsito&lt;/td&gt;&lt;td&gt;&lt;em&gt;in transit&lt;/em&gt; (ou &lt;em&gt;in motion&lt;/em&gt;)&lt;/td&gt;&lt;td&gt;Viajando pela rede&lt;/td&gt;&lt;td&gt;TLS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Em uso&lt;/td&gt;&lt;td&gt;&lt;em&gt;in use&lt;/em&gt;&lt;/td&gt;&lt;td&gt;Na memória, sendo processado&lt;/td&gt;&lt;td&gt;Criptografia no cliente, computação confidencial&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;“Repouso” é o dado descansando: gravado em algum lugar, esperando ser lido. Em português o termo soa um pouco estranho no começo, mas é o que aparece em normas e documentações traduzidas.&lt;/p&gt;
&lt;h2 id=&quot;criptografia-em-repouso&quot;&gt;Criptografia em repouso&lt;/h2&gt;
&lt;div class=&quot;caneta-moldura&quot;&gt;&lt;p&gt;A ideia é simples: tudo o que o banco grava fica cifrado. Arquivos de dados, logs, backups e snapshots. Se alguém sair com o disco, copiar o volume ou conseguir um snapshot, vai encontrar só bytes sem sentido.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Na maioria das implementações ela é &lt;strong&gt;transparente&lt;/strong&gt;: o banco (ou o storage por baixo dele) cifra ao gravar e decifra ao ler, e a aplicação não percebe nada. Não muda query, não muda driver. Quando é o próprio banco que cifra os arquivos, o recurso costuma se chamar TDE, de &lt;em&gt;Transparent Data Encryption&lt;/em&gt;, como no Oracle e no SQL Server. No RDS, a criptografia acontece no storage, e &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;a AWS não a chama de TDE&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;é no storage, não no banco&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;h3 id=&quot;onde-entra-o-kms&quot;&gt;Onde entra o KMS&lt;/h3&gt;
&lt;p&gt;A frase do começo fala em KMS. O KMS (&lt;em&gt;Key Management Service&lt;/em&gt;) é o cofre de chaves, e &lt;mark class=&quot;caneta-grifo&quot;&gt;o esquema usado quase sempre é o de &lt;strong&gt;envelope encryption&lt;/strong&gt;&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;Na lousa, o banco fica à esquerda, a chave de dados no meio e o KMS, com a chave mestra, no canto. O que a caneta risca deixou de valer, e o que ela escreve embaixo é o novo estado. O play monta tudo desde o início, e um clique num passo da lista leva a lousa até ele.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Diagrama do envelope encryption: os dados no disco, cifrados com a chave de dados; a chave de dados guardada cifrada pela chave mestra, que fica no KMS; o banco pedindo ao KMS para abrir a chave de dados; e, com a chave mestra desativada, o KMS recusando o pedido e os dados e os backups ficando ilegíveis.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/criptografia-em-repouso-e-em-transito/&quot;&gt;A lousa interativa está no site.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;O ganho é que o acesso ao dado passa a depender também de quem pode usar a chave. Se a chave for desativada ou apagada, os dados ficam ilegíveis, inclusive os backups. Tirar a permissão de um usuário &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;não basta&lt;/span&gt;: no RDS, o banco guarda uma autorização própria na chave (um &lt;em&gt;grant&lt;/em&gt;), criada junto com a instância.&lt;/p&gt;
&lt;h3 id=&quot;o-que-ela-protege-e-o-que-não-protege&quot;&gt;O que ela protege e o que não protege&lt;/h3&gt;
&lt;p&gt;Ela protege contra:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;roubo ou descarte indevido de disco;&lt;/li&gt;
&lt;li&gt;acesso a snapshots e backups por quem não tem permissão na chave;&lt;/li&gt;
&lt;li&gt;parte das exigências de auditoria: as normas do Banco Central (Resolução CMN 4.893) põem a criptografia entre os controles mínimos de segurança cibernética, e a LGPD, que pede medidas de segurança sem citar a criptografia, leva em conta, num incidente, se os dados vazados estavam ininteligíveis. Para número de cartão ela ajuda, mas não basta: desde a versão 4.0, o PCI DSS (&lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;requisito 3.5.1.2&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;vale desde 31/03/2025&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) não aceita a criptografia de disco como única proteção do número do cartão, e é preciso também tokenizar, truncar ou cifrar o campo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ela &lt;strong&gt;não&lt;/strong&gt; protege contra:&lt;/p&gt;
&lt;div class=&quot;caneta-chave&quot;&gt;&lt;ul class=&quot;caneta-lista caneta-chave-lista&quot;&gt;
&lt;li&gt;quem tem usuário e senha do banco. Para essa pessoa, o dado aparece em texto claro, porque a decifragem acontece por baixo;&lt;/li&gt;
&lt;li&gt;uma aplicação comprometida ou uma injeção de SQL;&lt;/li&gt;
&lt;li&gt;o dado viajando pela rede. Para isso existe a criptografia em trânsito.&lt;/li&gt;
&lt;/ul&gt;&lt;div class=&quot;caneta-chave-lado&quot;&gt;&lt;span class=&quot;caneta-escrita caneta-chave-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;nada disso muda com o disco cifrado&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;O primeiro item é o mais mal-entendido.&lt;/p&gt;
&lt;blockquote class=&quot;frase-destaque&quot; data-frase-destaque&gt;&lt;p&gt;&lt;span class=&quot;palavra&quot;&gt;Criptografia&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;em&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;repouso&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;não&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;é&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;controle&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;de&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;acesso.&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;mark class=&quot;caneta-marca&quot;&gt;Ela protege o &lt;strong&gt;meio&lt;/strong&gt; onde o dado está gravado, e não o dado contra quem pode consultá-lo.&lt;/mark&gt;&lt;/p&gt;
&lt;h2 id=&quot;criptografia-em-trânsito&quot;&gt;Criptografia em trânsito&lt;/h2&gt;
&lt;p&gt;Aqui o dado está saindo da aplicação e indo para o banco, voltando, ou indo de um nó do cluster para outro. A proteção é o TLS, o mesmo protocolo do HTTPS, e ele resolve dois problemas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sigilo:&lt;/strong&gt; quem intercepta o tráfego não consegue ler.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autenticidade:&lt;/strong&gt; quando o cliente valida o certificado, ele tem certeza de que está falando com o banco certo, e não com alguém no meio do caminho.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;O segundo ponto é o que mais se perde na prática. Muita configuração liga o TLS mas não valida o certificado. O tráfego fica cifrado, mas nada impede um ataque &lt;em&gt;man-in-the-middle&lt;/em&gt;. No Postgres, essa é a diferença entre &lt;code&gt;sslmode=require&lt;/code&gt;, que cifra mas não confere quem está do outro lado, e &lt;code&gt;sslmode=verify-full&lt;/code&gt;, que confere a CA e o nome do servidor.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Na lousa, as duas linhas mostram a mesma conexão, com alguém no meio do caminho: em cima, com &lt;code&gt;require&lt;/code&gt;; embaixo, com &lt;code&gt;verify-full&lt;/code&gt;. Arraste sobre o desenho para andar no tempo.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Linha do tempo comparando sslmode=require e sslmode=verify-full: um intermediário se passa pelo banco com um certificado próprio; com require, o cliente aceita e o intermediário lê o tráfego; com verify-full, o cliente confere a CA e o nome do servidor e recusa a conexão.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/criptografia-em-repouso-e-em-transito/&quot;&gt;A lousa interativa está no site.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A própria documentação do PostgreSQL resume isso numa tabela: com &lt;code&gt;require&lt;/code&gt;, a coluna de proteção contra &lt;em&gt;man-in-the-middle&lt;/em&gt; diz “No”; só com &lt;code&gt;verify-full&lt;/code&gt; ela diz “Yes”.&lt;/p&gt;
&lt;figure class=&quot;evidencia&quot; data-astro-cid-zafmdbgc&gt;&lt;a class=&quot;evidencia-imagem&quot; href=&quot;https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-astro-cid-zafmdbgc&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/_astro/sslmode.C9DQlY8K_Zsoji8.webp&quot; srcset=&quot;/_astro/sslmode.C9DQlY8K_2vV3kV.webp 640w, /_astro/sslmode.C9DQlY8K_ZAJ66M.webp 1120w, /_astro/sslmode.C9DQlY8K_Zk6LQP.webp 1600w&quot; alt=&quot;Tabela da documentação do PostgreSQL com os valores de sslmode: require protege contra escuta, mas não contra man-in-the-middle; verify-full protege contra os dois; prefer, o padrão, não protege contra man-in-the-middle.&quot; sizes=&quot;(max-width: 760px) 100vw, 760px&quot; data-astro-cid-zafmdbgc=&quot;true&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1896&quot; height=&quot;774&quot;&gt;&lt;/a&gt;&lt;figcaption data-astro-cid-zafmdbgc&gt;Documentação do PostgreSQL, a tabela dos modos de sslmode · &lt;a href=&quot;https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-astro-cid-zafmdbgc&gt;postgresql.org&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;postgresql-no-amazon-rds&quot;&gt;PostgreSQL no Amazon RDS&lt;/h2&gt;
&lt;h3 id=&quot;em-repouso&quot;&gt;Em repouso&lt;/h3&gt;
&lt;p&gt;No &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;RDS&lt;/span&gt;, a criptografia em repouso &lt;span class=&quot;caneta caneta-duplo&quot;&gt;é ligada na criação da instância&lt;/span&gt; e usa uma chave do AWS KMS. Ela cobre o storage, os backups automáticos, os snapshots, os logs e as réplicas de leitura. No console é a opção &lt;em&gt;Enable encryption&lt;/em&gt;. Na API, na CLI e no CloudFormation é o &lt;code&gt;StorageEncrypted&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pela CLI:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot; style=&quot;--linhas:9&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Janela do terminal&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;create-db-instance&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-instance-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-db&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--engine&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;postgres&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-instance-class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;db.t4g.medium&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--allocated-storage&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--master-username&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pgadmin&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--manage-master-user-password&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;&lt;span class=&quot;caneta-codigo-circulo longo&quot;&gt;--storage-encrypted&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;é isto que liga&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--kms-key-id&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;alias/rds-pedidos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Com Terraform:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:15&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;main.tf&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;HCL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;hcl&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &amp;quot;aws_kms_key&amp;quot; &amp;quot;rds&amp;quot; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;description &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Chave do RDS de pedidos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &amp;quot;aws_db_instance&amp;quot; &amp;quot;pedidos&amp;quot; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;identifier                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-db&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;engine                      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;postgres&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;instance_class              &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;db.t4g.medium&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;allocated_storage           &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;username                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pgadmin&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;manage_master_user_password &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:2&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;storage_encrypted &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;kms_key_id        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; aws_kms_key&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;arn&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;liga e escolhe a chave&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para conferir as instâncias que você já tem:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot; style=&quot;--linhas:3&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Janela do terminal&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;describe-db-instances&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--query&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;DBInstances[].{instancia:DBInstanceIdentifier,criptografada:StorageEncrypted,chave:KmsKeyId}&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--output&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;table&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside class=&quot;aviso&quot; data-aviso=&quot;nota&quot; aria-label=&quot;Nota&quot;&gt;&lt;div class=&quot;aviso-corpo&quot;&gt;&lt;p&gt;&lt;strong class=&quot;aviso-rotulo&quot;&gt;Nota.&lt;/strong&gt; O Aurora mudou em 2026: todo cluster criado a partir de 18/02/2026 já nasce cifrado, com uma chave da própria AWS quando você não escolhe outra. Nesse caso, o &lt;code&gt;StorageEncrypted&lt;/code&gt; aparece &lt;code&gt;false&lt;/code&gt;, e quem mostra a criptografia é o campo novo &lt;code&gt;StorageEncryptionType&lt;/code&gt; (&lt;code&gt;sse-rds&lt;/code&gt;). No RDS, fora do Aurora, a criptografia continua sendo uma escolha na criação.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Três pontos de atenção:&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-asterisco&quot;&gt;&lt;p&gt;&lt;strong&gt;Não dá para ligar numa instância que já existe.&lt;/strong&gt; O caminho é tirar um snapshot, copiar o snapshot informando uma chave KMS (a cópia sai criptografada) e restaurar uma instância nova a partir dela. Isso significa uma instância nova, com outro endpoint (a menos que você renomeie a antiga e dê o nome dela à nova), e janela de manutenção. Se o downtime for um problema, dá para migrar com replicação lógica ou AWS DMS.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot; style=&quot;--linhas:16&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Janela do terminal&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;create-db-snapshot&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-instance-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-db&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-snapshot-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-sem-cripto&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;wait&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;db-snapshot-available&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-snapshot-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-sem-cripto&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;copy-db-snapshot&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--source-db-snapshot-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-sem-cripto&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--target-db-snapshot-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-cripto&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--kms-key-id&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;alias/rds-pedidos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;wait&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;db-snapshot-available&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-snapshot-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-cripto&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;rds&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;restore-db-instance-from-db-snapshot&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-instance-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-db-v2&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--db-snapshot-identifier&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pedidos-cripto&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Na restauração, informe também o parameter group e os security groups da instância original (&lt;code&gt;--db-parameter-group-name&lt;/code&gt; e &lt;code&gt;--vpc-security-group-ids&lt;/code&gt;). Sem eles, o RDS usa os padrões, e um &lt;code&gt;rds.&lt;wbr/&gt;force_ssl = 1&lt;/code&gt; configurado à mão, como na seção seguinte, se perde.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Réplicas herdam a criptografia.&lt;/strong&gt; Uma réplica de uma primária criptografada é obrigatoriamente criptografada, e é daí que vem o “como a primária” da frase do começo. &lt;mark class=&quot;caneta-grifo&quot;&gt;Uma réplica em outra região usa uma chave KMS daquela região.&lt;/mark&gt;&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-visto&quot;&gt;&lt;p&gt;&lt;strong&gt;Prefira uma chave gerenciada por você&lt;/strong&gt; (&lt;em&gt;customer managed key&lt;/em&gt;) em vez da padrão &lt;code&gt;aws/rds&lt;/code&gt;. Com a chave padrão, não dá para compartilhar snapshots com outra conta AWS, e você não controla a política de acesso da chave.&lt;/p&gt;&lt;/div&gt;
&lt;h3 id=&quot;em-trânsito&quot;&gt;Em trânsito&lt;/h3&gt;
&lt;p&gt;O RDS já cria o certificado da instância. Faltam duas coisas: o servidor exigir TLS e &lt;span class=&quot;caneta caneta-duplo&quot;&gt;o cliente validar o certificado&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;No servidor, quem manda é o parâmetro &lt;code&gt;rds.&lt;wbr/&gt;force_ssl&lt;/code&gt;. A partir do &lt;span class=&quot;caneta caneta-circulo longo&quot;&gt;PostgreSQL 15&lt;/span&gt; ele já vem ligado (&lt;code&gt;1&lt;/code&gt;) por padrão. Nas versões anteriores ele vem desligado, e você precisa criar um &lt;em&gt;parameter group&lt;/em&gt; customizado com &lt;code&gt;rds.&lt;wbr/&gt;force_ssl = 1&lt;/code&gt; e associá-lo à instância (com reboot, se ela já estiver rodando).&lt;/p&gt;
&lt;p&gt;No cliente, baixe o pacote de certificados da AWS e use &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;verify-full&lt;/code&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Janela do terminal&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;curl &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-o&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;global-bundle.pem&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;psql &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;host=pedidos-db.xxxx.sa-east-1.rds.amazonaws.com port=5432 dbname=pedidos &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;user=app sslmode=verify-full sslrootcert=global-bundle.pem&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Em &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://jdbc.postgresql.org/documentation/ssl/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Java&lt;/span&gt;, pela URL do JDBC:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;jdbc:postgresql://pedidos-db.xxxx.sa-east-1.rds.amazonaws.com:5432/pedidos?sslmode=verify-full&amp;amp;sslrootcert=/etc/certs/global-bundle.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Por que não confiar no padrão? Porque tanto o &lt;code&gt;psql&lt;/code&gt; quanto o driver JDBC usam &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;&lt;code&gt;sslmode=prefer&lt;/code&gt;&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;aceita conexão sem TLS&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: tentam TLS, aceitam cair para uma conexão sem criptografia e não validam o certificado.&lt;/p&gt;
&lt;p&gt;Para ver quem está conectado com TLS (com o usuário mestre ou um usuário com &lt;code&gt;pg_monitor&lt;/code&gt;, porque um usuário comum só vê as próprias sessões):&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;usename&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;client_addr&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;ssl&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;span class=&quot;caneta-codigo-circulo&quot;&gt;pg_stat_ssl&lt;/span&gt; s&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;uma linha por conexão&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JOIN&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pg_stat_activity a &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;pid&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;pid&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;backend_type&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;client backend&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;postgresql-fora-do-rds&quot;&gt;PostgreSQL fora do RDS&lt;/h2&gt;
&lt;h3 id=&quot;em-trânsito-1&quot;&gt;Em trânsito&lt;/h3&gt;
&lt;p&gt;O TLS é nativo no Postgres. Com o certificado e a chave do servidor em mãos (de uma CA interna ou pública), &lt;mark class=&quot;caneta-grifo&quot;&gt;é só configuração&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;No &lt;code&gt;postgresql.&lt;wbr/&gt;conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;postgresql.conf&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;INI&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;ini&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; on&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl_cert_file&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/etc/postgresql/tls/server.crt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl_key_file&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/etc/postgresql/tls/server.key&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl_min_protocol_version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;TLSv1.2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;O arquivo da chave precisa pertencer ao usuário &lt;code&gt;postgres&lt;/code&gt;, com permissão &lt;code&gt;0600&lt;/code&gt;, ou ao &lt;code&gt;root&lt;/code&gt;, com &lt;code&gt;0640&lt;/code&gt; e o &lt;code&gt;postgres&lt;/code&gt; no grupo do arquivo. Senão, o servidor se recusa a usá-lo.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;No &lt;code&gt;pg_hba.&lt;wbr/&gt;conf&lt;/code&gt;, aceite conexões remotas só com TLS. Essas linhas entram no lugar das linhas &lt;code&gt;host&lt;/code&gt; que já existem, porque &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;vale a primeira linha que casar&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;pg_hba.conf&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;# TYPE     DATABASE  USER  ADDRESS     METHOD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;hostssl    all       all   0.0.0.0/0   scram-sha-256&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;hostssl    all       all   ::/0        scram-sha-256&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:2&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;hostnossl  all       all   0.0.0.0/0   reject&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;hostnossl  all       all   ::/0        reject&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;sem TLS, recusado&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-carimbado&quot;&gt;&lt;p&gt;Depois, recarregue a configuração com &lt;code&gt;SELECT pg_reload_conf();&lt;/code&gt; e confira no log que não apareceu &lt;code&gt;SSL configuration was not reloaded&lt;/code&gt;. No cliente vale a mesma regra do RDS: &lt;code&gt;sslmode=verify-full&lt;/code&gt;, com &lt;code&gt;sslrootcert&lt;/code&gt; apontando para a CA que assinou o certificado do servidor.&lt;/p&gt;&lt;p class=&quot;caneta-carimbo&quot;&gt;&lt;span class=&quot;caneta-carimbo-selo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt;Carimbo: &lt;/span&gt;testado no Postgres 16&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;
&lt;h3 id=&quot;em-repouso-1&quot;&gt;Em repouso&lt;/h3&gt;
&lt;div class=&quot;caneta-margem caneta-colchete&quot;&gt;&lt;p&gt;Aqui está a maior diferença em relação ao RDS: &lt;strong&gt;o PostgreSQL da comunidade não tem criptografia em repouso nativa.&lt;/strong&gt; Não existe um &lt;code&gt;ssl = on&lt;/code&gt; para o disco. As opções são três.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. Criptografar o volume.&lt;/strong&gt; LUKS (dm-crypt) em servidor próprio, ou um volume criptografado na nuvem, como um EBS criptografado numa EC2. &lt;span class=&quot;caneta caneta-duplo&quot;&gt;É o caminho mais comum&lt;/span&gt;, e protege contra roubo do disco e de snapshots do volume.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot; style=&quot;--linhas:6&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Janela do terminal&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Atenção: apaga o disco. Use um disco dedicado aos dados.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;cryptsetup &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;luksFormat&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/dev/nvme1n1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;cryptsetup &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/dev/nvme1n1&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pgdata&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mkfs.xfs &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/dev/mapper/pgdata&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mount &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/dev/mapper/pgdata&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/var/lib/postgresql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# depois: chown postgres:postgres /var/lib/postgresql e as entradas no /etc/crypttab e no /etc/fstab&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A limitação é que, com o volume montado, o sistema de arquivos &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;já enxerga tudo decifrado&lt;/span&gt;. Quem tem acesso ao servidor ligado lê os arquivos normalmente. Também é preciso decidir como o volume é destravado no boot (senha manual, TPM, Clevis/Tang), e essa é a parte que dá trabalho.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Usar TDE de uma distribuição.&lt;/strong&gt; O Percona Distribution for PostgreSQL tem a extensão open source &lt;code&gt;pg_tde&lt;/code&gt;, que cifra dentro do próprio banco as tabelas criadas com &lt;code&gt;tde_heap&lt;/code&gt; (com os índices delas e, se você ligar, o WAL), com as chaves guardadas num Vault, OpenBao ou servidor KMIP. Ela depende do &lt;span class=&quot;caneta caneta-circulo longo&quot;&gt;Percona Server for PostgreSQL&lt;/span&gt;, uma versão do Postgres modificada pela Percona, e não roda no Postgres da comunidade. Há também opções comerciais, como o EDB Postgres Advanced Server.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:10&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- postgresql.conf: shared_preload_libraries = &amp;#39;pg_tde&amp;#39; (e reinicie o servidor)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; EXTENSION pg_tde;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- configure o provedor de chaves (Vault, OpenBao ou KMIP) e a chave principal;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- as funções mudam entre versões, então siga a documentação da versão instalada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TABLE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cartao (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id     &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;numero &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;USING&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;span class=&quot;caneta-codigo-circulo&quot;&gt;tde_heap&lt;/span&gt;;&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;só estas tabelas são cifradas&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;3. Não esquecer dos backups.&lt;/strong&gt; Um banco criptografado com backups em texto claro num bucket qualquer não resolve nada. O pgBackRest, por exemplo, cifra o repositório de backups com &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;repo1-cipher-type=aes-256-cbc&lt;/code&gt;&lt;/span&gt; e &lt;code&gt;repo1-cipher-pass&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;mongodb-atlas&quot;&gt;MongoDB Atlas&lt;/h2&gt;
&lt;h3 id=&quot;em-repouso-2&quot;&gt;Em repouso&lt;/h3&gt;
&lt;p&gt;No &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://www.mongodb.com/docs/atlas/security-kms-encryption/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Atlas&lt;/span&gt;, a criptografia em repouso &lt;mark class=&quot;caneta-grifo&quot;&gt;já vem ligada em todos os clusters&lt;/mark&gt;, sem configuração. O Atlas usa a criptografia de volume do provedor de nuvem (na AWS, EBS criptografado).&lt;/p&gt;
&lt;p&gt;Se você precisa controlar a chave para rotacionar, revogar e auditar o uso, existe a opção &lt;strong&gt;Encryption at Rest using Customer Key Management&lt;/strong&gt;, também chamada de BYOK (&lt;em&gt;bring your own key&lt;/em&gt;). Com ela, o Atlas cifra os dados uma segunda vez, no Encrypted Storage Engine do MongoDB, usando uma chave sua no AWS KMS, no Azure Key Vault ou no Google Cloud KMS. Ela só está disponível em clusters dedicados, do &lt;span class=&quot;caneta caneta-circulo&quot;&gt;M10&lt;/span&gt; para cima.&lt;/p&gt;
&lt;p&gt;Na AWS, os passos são:&lt;/p&gt;
&lt;ol class=&quot;caneta-lista caneta-passos&quot;&gt;
&lt;li&gt;&lt;span class=&quot;caneta-numero&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;Criar uma chave simétrica no AWS KMS.&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;caneta-numero&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;Criar um IAM role que o Atlas possa assumir, com permissão de &lt;code&gt;kms:Encrypt&lt;/code&gt;, &lt;code&gt;kms:Decrypt&lt;/code&gt; e &lt;code&gt;kms:DescribeKey&lt;/code&gt; nessa chave.&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;caneta-numero&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;No projeto do Atlas, configurar o Encryption at Rest com o AWS KMS, informando a chave, a região e o role.&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;caneta-numero&quot; aria-hidden=&quot;true&quot;&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;Ligar a opção em cada cluster que deve usar a chave.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Com Terraform:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:17&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;main.tf&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;HCL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;hcl&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &amp;quot;mongodbatlas_encryption_at_rest&amp;quot; &amp;quot;this&amp;quot; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;project_id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; var&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;atlas_project_id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;aws_kms_config&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;enabled                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;customer_master_key_id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; aws_kms_key&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;atlas&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;region                 &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;SA_EAST_1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;role_id                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; mongodbatlas_cloud_provider_access_authorization&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;atlas&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;role_id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &amp;quot;mongodbatlas_advanced_cluster&amp;quot; &amp;quot;pedidos&amp;quot; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# o project_id vem do recurso acima, para o cluster esperar a criptografia estar configurada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:2&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;project_id                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; mongodbatlas_encryption_at_rest&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;project_id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;encryption_at_rest_provider &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;AWS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;o cluster espera a chave&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# ... demais configurações do cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Um cuidado: se a chave for desativada ou apagada, ou se o role perder a permissão, o Atlas percebe na verificação seguinte (ele confere a cada 15 minutos) e desliga os processos do cluster. Ninguém lê nem grava até a chave voltar, e os snapshots cifrados com ela não podem ser restaurados. É o outro lado de ter o controle da chave.&lt;/p&gt;&lt;/div&gt;
&lt;h3 id=&quot;em-trânsito-2&quot;&gt;Em trânsito&lt;/h3&gt;
&lt;div class=&quot;caneta-margem caneta-validade&quot;&gt;&lt;span class=&quot;caneta-sinal-margem caneta-validade-onda&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;p&gt;No Atlas, o TLS é obrigatório e não dá para desligar. A string de conexão &lt;code&gt;mongodb+srv://&lt;/code&gt; já liga o TLS no driver. O que dá para ajustar é a versão mínima do TLS nas configurações do cluster: o Atlas já recusa o 1.0 e o 1.1, então a escolha é entre 1.2 e 1.3.&lt;/p&gt;&lt;/div&gt;
&lt;p class=&quot;caneta-escrita caneta-validade-nota&quot;&gt;conferido em set/2026&lt;/p&gt;
&lt;h2 id=&quot;mongodb-fora-do-atlas&quot;&gt;MongoDB fora do Atlas&lt;/h2&gt;
&lt;h3 id=&quot;em-trânsito-3&quot;&gt;Em trânsito&lt;/h3&gt;
&lt;p&gt;No &lt;code&gt;mongod.&lt;wbr/&gt;conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:10&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;mongod.conf&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;YAML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;27017&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bindIp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;127.0.0.1,10.0.1.15&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tls&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;mode&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&lt;span class=&quot;caneta-codigo-circulo&quot;&gt;requireTLS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;recusa conexão sem TLS&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;certificateKeyFile&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/etc/mongodb/tls/mongod.pem&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# certificado + chave privada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CAFile&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/etc/mongodb/tls/ca.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# clientes sem certificado autenticam com usuário e senha (security.authorization ligado)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;allowConnectionsWithoutCertificates&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;disabledProtocols&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;TLS1_0,TLS1_1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Com &lt;code&gt;requireTLS&lt;/code&gt;, a comunicação entre os membros do replica set também passa a exigir TLS. Se o certificado não tiver o uso &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;clientAuth&lt;/code&gt;&lt;/span&gt;, os membros não conseguem conversar entre si. Gere-o com &lt;code&gt;clientAuth&lt;/code&gt; ou use &lt;code&gt;setParameter: tlsWithholdClientCertificate: true&lt;/code&gt; com autenticação interna por keyFile.&lt;/p&gt;
&lt;p&gt;Para migrar um ambiente que já está no ar sem derrubar tudo, reinicie os membros um de cada vez com &lt;code&gt;allowTLS&lt;/code&gt;, passe os clientes para TLS e só então troque todos para &lt;code&gt;preferTLS&lt;/code&gt; e, por fim, para &lt;code&gt;requireTLS&lt;/code&gt; (com &lt;code&gt;setParameter&lt;/code&gt;, sem reiniciar). Cada etapa precisa chegar a &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;todos os membros&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;senão, o primário cai&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; antes da próxima, e no fim o &lt;code&gt;mongod.&lt;wbr/&gt;conf&lt;/code&gt; fica com &lt;code&gt;requireTLS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;No cliente:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;mongodb://app:&amp;lt;senha&amp;gt;@mongo1.interno:27017,mongo2.interno:27017/?replicaSet=rs0&amp;amp;tls=true&amp;amp;tlsCAFile=/etc/certs/ca.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;em-repouso-3&quot;&gt;Em repouso&lt;/h3&gt;
&lt;p&gt;Aqui depende da edição do MongoDB.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Community:&lt;/strong&gt; &lt;mark class=&quot;caneta-grifo&quot;&gt;não tem criptografia em repouso nativa&lt;/mark&gt;. O caminho é o mesmo do Postgres autogerenciado: volume criptografado (LUKS, EBS criptografado e afins).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enterprise:&lt;/strong&gt; tem o Encrypted Storage Engine, que cifra os arquivos do WiredTiger. O recomendado é que a chave mestra &lt;span class=&quot;caneta caneta-duplo&quot;&gt;venha de um servidor KMIP&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:7&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;mongod.conf&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;YAML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enableEncryption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;kmip&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;serverName&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;kmip.interno&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;5696&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;serverCAFile&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/etc/mongodb/kmip/ca.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;clientCertificateFile&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;/etc/mongodb/kmip/mongod-client.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-visto&quot;&gt;&lt;p&gt;Também existe a opção &lt;code&gt;encryptionKeyFile&lt;/code&gt;, com a chave num arquivo local. Ela deixa a chave no mesmo servidor dos dados e, segundo a própria MongoDB, não atende à maioria das exigências regulatórias de gestão de chaves. Em produção, prefira o KMIP.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Percona Server for MongoDB:&lt;/strong&gt; alternativa gratuita e compatível com o MongoDB, de código-fonte disponível (&lt;span class=&quot;caneta caneta-aspas&quot;&gt;&lt;em&gt;source available&lt;/em&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (entre aspas)&lt;/span&gt;&lt;/span&gt;, pela licença SSPL), que também tem criptografia em repouso, com as chaves num Vault (ou OpenBao) ou num servidor KMIP.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-asterisco&quot;&gt;&lt;p&gt;Um detalhe operacional: não dá para ligar a criptografia em cima de arquivos que já existem. Num replica set, o jeito é fazer membro a membro, começando pelos secundários e, por último, o primário, depois de um &lt;code&gt;rs.&lt;wbr/&gt;stepDown()&lt;/code&gt;: parar o membro, limpar o &lt;code&gt;dbPath&lt;/code&gt;, subir com a criptografia ligada e deixar o &lt;em&gt;initial sync&lt;/em&gt; repopular os dados.&lt;/p&gt;&lt;/div&gt;
&lt;h2 id=&quot;e-a-criptografia-em-uso&quot;&gt;E a criptografia em uso?&lt;/h2&gt;
&lt;p&gt;Existe um terceiro estado, bem menos comum no dia a dia: o dado &lt;strong&gt;em uso&lt;/strong&gt;, enquanto está na memória sendo processado.&lt;/p&gt;
&lt;p&gt;Repare que as duas proteções anteriores têm um ponto cego em comum: &lt;mark class=&quot;caneta-marca&quot;&gt;dentro do servidor do banco, o dado fica aberto&lt;/mark&gt;. Um DBA, um backup lógico (&lt;code&gt;pg_dump&lt;/code&gt;, &lt;code&gt;mongodump&lt;/code&gt;) ou alguém que invadiu o servidor enxerga tudo.&lt;/p&gt;
&lt;p&gt;A criptografia em uso tenta fechar esse buraco. Um bom exemplo é o &lt;strong&gt;Queryable Encryption&lt;/strong&gt; do MongoDB. A aplicação cifra os campos sensíveis no próprio driver, antes de enviar, e o servidor guarda e consulta o dado &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;sem nunca ver o valor original&lt;/span&gt;. A chave mestra fica num KMS que só a aplicação acessa. O banco guarda apenas as chaves de dados, cifradas por ela, e nunca consegue abri-las.&lt;/p&gt;
&lt;p&gt;A figura põe as proteções lado a lado. Cada linha é uma proteção, e cada coluna, um lugar por onde o dado passa, da aplicação ao disco. O cadeado fechado, na cor da proteção, é onde o dado está cifrado; o aberto, em vermelho, é onde ele aparece em texto claro. Com repouso e trânsito juntos, o servidor do banco continua aberto (o quadro que pisca); com a criptografia em uso, só a aplicação vê o valor. Com o mouse numa cor da legenda, a figura destaca só aquela proteção.&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 700&quot;
  aria-label=&quot;Quadro com quatro linhas e quatro lugares por onde o dado passa: aplicação, rede, servidor e disco. Só em trânsito, só a rede fica cifrada; só em repouso, só o disco; com os dois juntos, o servidor continua aberto; com a criptografia em uso, só a aplicação vê o dado.&quot;&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;referencia&quot;&gt;
      &lt;path d=&quot;M1020 52 A30 8 0 0 1 1080 52 V96 A30 8 0 0 1 1020 96 Z&quot; class=&quot;papel&quot;/&gt;
      &lt;path d=&quot;M1020 52 A30 8 0 0 1 1080 52 V96 A30 8 0 0 1 1020 96 Z M1020 52 A30 8 0 0 0 1080 52&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M560 80 C 585 50 600 110 625 80 C 640 62 650 70 662 76&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M548 80 m-7 0 a7 7 0 1 0 14 0 a7 7 0 1 0 -14 0 M674 78 m-7 0 a7 7 0 1 0 14 0 a7 7 0 1 0 -14 0&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;path d=&quot;M480 262 H520 M700 262 H740 M920 262 H960&quot; class=&quot;fantasma&quot;/&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;300&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;300&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M372 256 H408 V282 H372 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M379 256 V240 A11 11 0 0 1 401 240 V246&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-petroleo&quot;&gt;&lt;rect x=&quot;520&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M592 252 H628 V278 H592 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M599 252 V244 A11 11 0 0 1 621 244 V252&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;740&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;740&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M812 256 H848 V282 H812 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M819 256 V240 A11 11 0 0 1 841 240 V246&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;960&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;222&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M1032 256 H1068 V282 H1032 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M1039 256 V240 A11 11 0 0 1 1061 240 V246&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;path d=&quot;M480 372 H520 M700 372 H740 M920 372 H960&quot; class=&quot;fantasma&quot;/&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;300&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;300&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M372 366 H408 V392 H372 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M379 366 V350 A11 11 0 0 1 401 350 V356&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;520&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M592 366 H628 V392 H592 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M599 366 V350 A11 11 0 0 1 621 350 V356&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;740&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;740&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M812 366 H848 V392 H812 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M819 366 V350 A11 11 0 0 1 841 350 V356&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-ambar&quot;&gt;&lt;rect x=&quot;960&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;332&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M1032 362 H1068 V388 H1032 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M1039 362 V354 A11 11 0 0 1 1061 354 V362&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;path d=&quot;M480 482 H520 M700 482 H740 M920 482 H960&quot; class=&quot;fantasma&quot;/&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;300&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;300&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M372 476 H408 V502 H372 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M379 476 V460 A11 11 0 0 1 401 460 V466&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-petroleo&quot;&gt;&lt;rect x=&quot;520&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M592 472 H628 V498 H592 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M599 472 V464 A11 11 0 0 1 621 464 V472&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;740&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;740&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M812 476 H848 V502 H812 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M819 476 V460 A11 11 0 0 1 841 460 V466&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-ambar&quot;&gt;&lt;rect x=&quot;960&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;442&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M1032 472 H1068 V498 H1032 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M1039 472 V464 A11 11 0 0 1 1061 464 V472&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;path d=&quot;M480 592 H520 M700 592 H740 M920 592 H960&quot; class=&quot;fantasma&quot;/&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;300&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;&lt;rect x=&quot;300&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;fantasma&quot;/&gt;&lt;path d=&quot;M372 586 H408 V612 H372 Z&quot; class=&quot;linha-tom&quot;/&gt;&lt;path d=&quot;M379 586 V570 A11 11 0 0 1 401 570 V576&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;&lt;rect x=&quot;520&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;520&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M592 582 H628 V608 H592 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M599 582 V574 A11 11 0 0 1 621 574 V582&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;&lt;rect x=&quot;740&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;740&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;740&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M812 582 H848 V608 H812 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M819 582 V574 A11 11 0 0 1 841 574 V582&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;&lt;rect x=&quot;960&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;&lt;rect x=&quot;960&quot; y=&quot;552&quot; width=&quot;180&quot; height=&quot;80&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;&lt;path d=&quot;M1032 582 H1068 V608 H1032 Z&quot; class=&quot;cheio-tom&quot;/&gt;&lt;path d=&quot;M1039 582 V574 A11 11 0 0 1 1061 574 V582&quot; class=&quot;linha-tom&quot;/&gt;&lt;/g&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;rect x=&quot;732&quot; y=&quot;434&quot; width=&quot;196&quot; height=&quot;96&quot; rx=&quot;16&quot; class=&quot;traco-tom pisca&quot;/&gt;&lt;/g&gt;

  &lt;path d=&quot;M300 292 H1140&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
  &lt;path d=&quot;M300 402 H1140&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-2&quot;/&gt;
  &lt;path d=&quot;M300 512 H1140&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-3&quot;/&gt;
  &lt;path d=&quot;M300 622 H1140&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-4&quot;/&gt;

  &lt;g class=&quot;referencia&quot;&gt;
    &lt;g transform=&quot;translate(360 40) scale(.62)&quot; class=&quot;marca marca-java&quot;&gt;&lt;g class=&quot;tinta tom-ambar&quot;&gt;
    &lt;path d=&quot;M38 39 C 31 33 44 27 37 20 C 32 15 37 10 41 7&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M55 39 C 48 33 61 27 54 20 C 50 16 53 12 56 10&quot; class=&quot;linha-tom&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M17 46 H73 V60 C73 75 62 84 45 84 C28 84 17 75 17 60 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M17 46 H73 V60 C73 75 62 84 45 84 C28 84 17 75 17 60 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M73 51 C 88 49 90 68 71 70&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M9 91 C 30 98 62 98 83 91&quot; class=&quot;linha-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
    &lt;g transform=&quot;translate(768 40) scale(.62)&quot; class=&quot;marca marca-postgresql&quot;&gt;&lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M46 12 C 64 12 77 24 77 40 C 77 55 67 65 54 66 C 48 66.5 47 60.3 41 59.3 C 40.1 61.2 37.3 67.1 35.6 70.7 C 33.9 74.3 33 77.7 30.9 81 C 28.7 84.4 26.1 88.8 22.7 90.7 C 19.3 92.6 13.4 93.2 10.4 92.2 C 7.3 91.2 5.1 86.9 4.2 84.7 C 3.4 82.5 4 80 5.1 79.1 C 6.2 78.2 9.3 78.7 10.8 79.3 C 12.2 80 12.9 82.5 13.6 82.8 C 14.4 83.1 14.7 82.6 15.3 81.3 C 15.9 80 16.6 77.6 17.1 75 C 17.7 72.3 17.8 69 18.4 65.3 C 19.1 61.6 20.6 54.8 21 52.7 C 19 42.7 17 32 24 22 C 29 15 37 12 46 12 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M46 12 C 64 12 77 24 77 40 C 77 55 67 65 54 66 C 48 66.5 47 60.3 41 59.3 C 40.1 61.2 37.3 67.1 35.6 70.7 C 33.9 74.3 33 77.7 30.9 81 C 28.7 84.4 26.1 88.8 22.7 90.7 C 19.3 92.6 13.4 93.2 10.4 92.2 C 7.3 91.2 5.1 86.9 4.2 84.7 C 3.4 82.5 4 80 5.1 79.1 C 6.2 78.2 9.3 78.7 10.8 79.3 C 12.2 80 12.9 82.5 13.6 82.8 C 14.4 83.1 14.7 82.6 15.3 81.3 C 15.9 80 16.6 77.6 17.1 75 C 17.7 72.3 17.8 69 18.4 65.3 C 19.1 61.6 20.6 54.8 21 52.7 C 19 42.7 17 32 24 22 C 29 15 37 12 46 12 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M52 24 C 62 16 82 16 90 28 C 97 40 94 58 82 64 C 74 68 62 66 58 58 C 54 50 50 34 52 24 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M52 24 C 62 16 82 16 90 28 C 97 40 94 58 82 64 C 74 68 62 66 58 58 C 54 50 50 34 52 24 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M62 27 C 73 23 84 29 86 41&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;circle cx=&quot;33&quot; cy=&quot;34&quot; r=&quot;1.5&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
    &lt;g transform=&quot;translate(830 40) scale(.62)&quot; class=&quot;marca marca-mongodb&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M50 5 C 43 16 26 27 24 46 C 22 64 36 76 46 81 L50 95 L54 81 C 64 76 78 64 76 46 C 74 27 57 16 50 5 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M50 5 C 43 16 26 27 24 46 C 22 64 36 76 46 81 L50 95 L54 81 C 64 76 78 64 76 46 C 74 27 57 16 50 5 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M50 16 C 51 38 51 60 50 90&quot; class=&quot;linha-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;

    &lt;text x=&quot;390&quot; y=&quot;146&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Aplicação&lt;/text&gt;
    &lt;text x=&quot;390&quot; y=&quot;176&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;o driver&lt;/text&gt;
    &lt;text x=&quot;610&quot; y=&quot;146&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Rede&lt;/text&gt;
    &lt;text x=&quot;610&quot; y=&quot;176&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;o caminho&lt;/text&gt;
    &lt;text x=&quot;830&quot; y=&quot;146&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Servidor&lt;/text&gt;
    &lt;text x=&quot;830&quot; y=&quot;176&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;a memória do banco&lt;/text&gt;
    &lt;text x=&quot;1050&quot; y=&quot;146&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Disco&lt;/text&gt;
    &lt;text x=&quot;1050&quot; y=&quot;176&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;backups e snapshots&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;258&quot; class=&quot;titulo-caixa texto-tom&quot;&gt;Em trânsito&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;288&quot; class=&quot;texto-caixa&quot;&gt;TLS&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;368&quot; class=&quot;titulo-caixa texto-tom&quot;&gt;Em repouso&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;398&quot; class=&quot;texto-caixa&quot;&gt;disco cifrado&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-petroleo tom-ambar&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;478&quot; class=&quot;titulo-caixa&quot;&gt;Os dois juntos&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-vermelho&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;508&quot; class=&quot;texto-caixa texto-tom&quot;&gt;o servidor fica aberto&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;588&quot; class=&quot;titulo-caixa texto-tom&quot;&gt;Em uso&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;&lt;text x=&quot;40&quot; y=&quot;618&quot; class=&quot;texto-caixa&quot;&gt;só a aplicação abre&lt;/text&gt;&lt;/g&gt;

  &lt;g class=&quot;legenda tom-petroleo&quot;&gt;&lt;rect x=&quot;40&quot; y=&quot;668&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;72&quot; y=&quot;682&quot; class=&quot;nota-pequena&quot;&gt;cifrado na rede&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-ambar&quot;&gt;&lt;rect x=&quot;300&quot; y=&quot;668&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;332&quot; y=&quot;682&quot; class=&quot;nota-pequena&quot;&gt;cifrado no disco&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-roxo&quot;&gt;&lt;rect x=&quot;570&quot; y=&quot;668&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;602&quot; y=&quot;682&quot; class=&quot;nota-pequena&quot;&gt;cifrado até no servidor&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-vermelho&quot;&gt;&lt;rect x=&quot;890&quot; y=&quot;668&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;922&quot; y=&quot;682&quot; class=&quot;nota-pequena&quot;&gt;em texto claro&lt;/text&gt;&lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;Cada cor é uma proteção: em trânsito (petróleo), em repouso (âmbar) e em uso (roxo); em vermelho, onde o dado fica em texto claro.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Imagine uma coleção de portadores de cartão com o CPF cifrado. A aplicação, que tem acesso à chave, consulta normalmente:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:2&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;JavaScript&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;portadores&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cpf&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;123.456.789-09&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// { nome: &amp;#39;Maria Souza&amp;#39;, cpf: &amp;#39;123.456.789-09&amp;#39;, ... }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Um DBA conectado direto no banco, sem a chave, vê isto:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:2&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;JavaScript&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;portadores&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;findOne&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// { nome: &amp;#39;Maria Souza&amp;#39;, &lt;span class=&quot;caneta-codigo-circulo&quot;&gt;cpf&lt;/span&gt;: Binary.createFromBase64(&amp;#39;DkH2...&amp;#39;, 6), __safeContent__: [ ... ], ... }&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;o CPF, cifrado&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O subtipo &lt;span class=&quot;caneta caneta-circulo&quot;&gt;&lt;code&gt;6&lt;/code&gt;&lt;/span&gt; é o formato de dado cifrado do MongoDB. O banco não consegue ler o CPF e, mesmo assim, consegue responder à consulta de igualdade. A cifragem automática do exemplo exige MongoDB Enterprise ou Atlas (7.0 ou mais novo) num replica set. Na Community, só com cifragem explícita no código.&lt;/p&gt;
&lt;p&gt;Outro exemplo é a computação confidencial, que protege o dado de quem controla a máquina (o host, o hypervisor, o operador da nuvem). Nas VMs com &lt;span class=&quot;caneta caneta-explica&quot;&gt;&lt;span class=&quot;caneta-explica-alvo&quot;&gt;AMD SEV-SNP ou Intel TDX&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-explica-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (quer dizer: &lt;/span&gt;memória cifrada&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, o processador cifra a memória da VM com uma chave que nem o hypervisor acessa. Nos &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;AWS&lt;/span&gt; Nitro Enclaves, a proteção vem do isolamento: uma VM à parte, sem rede externa, sem disco e sem acesso interativo. Nenhuma das duas impede quem tem credencial do banco de consultar o dado.&lt;/p&gt;
&lt;p&gt;No Postgres, o &lt;code&gt;pgcrypto&lt;/code&gt; pode parecer a mesma coisa, &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;mas não é&lt;/span&gt;. A chave e o valor aberto passam pelo servidor na própria query e podem acabar em logs. Para ter o efeito de “em uso”, a criptografia precisa acontecer na aplicação.&lt;/p&gt;
&lt;p&gt;Por que é pouco usado? Porque cobra caro:&lt;/p&gt;
&lt;div class=&quot;caneta-chave&quot;&gt;&lt;ul class=&quot;caneta-lista caneta-chave-lista&quot;&gt;
&lt;li&gt;a aplicação passa a gerenciar chaves e o esquema de criptografia dos campos;&lt;/li&gt;
&lt;li&gt;as consultas sobre campos cifrados ficam limitadas (nada de ordenar ou agregar livremente por eles);&lt;/li&gt;
&lt;li&gt;ferramentas de BI, pipelines de dados e o próprio suporte deixam de enxergar o valor.&lt;/li&gt;
&lt;/ul&gt;&lt;div class=&quot;caneta-chave-lado&quot;&gt;&lt;span class=&quot;caneta-escrita caneta-chave-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;o preço da criptografia em uso&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-visto&quot;&gt;&lt;p&gt;Por isso ela costuma ficar reservada para poucos campos muito sensíveis. Em domínios como o de cartões, a tokenização muitas vezes resolve o mesmo problema com menos atrito.&lt;/p&gt;&lt;/div&gt;
&lt;h2 id=&quot;resumo&quot;&gt;Resumo&lt;/h2&gt;






























&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Em repouso, Em trânsito&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Em repouso&lt;/th&gt;&lt;th&gt;Em trânsito&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Postgres no RDS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;StorageEncrypted&lt;/code&gt; na criação, com chave no KMS. Instância existente só via cópia criptografada do snapshot&lt;/td&gt;&lt;td&gt;&lt;code&gt;rds.&lt;wbr/&gt;force_ssl = 1&lt;/code&gt; (padrão a partir do 15) e cliente com &lt;code&gt;verify-full&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Postgres fora do RDS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Volume criptografado (LUKS, EBS) ou TDE de distribuição (&lt;code&gt;pg_tde&lt;/code&gt;, EDB). Cifrar também os backups&lt;/td&gt;&lt;td&gt;&lt;code&gt;ssl = on&lt;/code&gt;, &lt;code&gt;hostssl&lt;/code&gt; e &lt;code&gt;hostnossl reject&lt;/code&gt; no &lt;code&gt;pg_hba.&lt;wbr/&gt;conf&lt;/code&gt;, cliente com &lt;code&gt;verify-full&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;MongoDB Atlas&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Sempre ligada. Chave própria (BYOK) a partir do M10&lt;/td&gt;&lt;td&gt;Sempre ligado, com TLS 1.2 ou 1.3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;MongoDB fora do Atlas&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Community: volume criptografado. Enterprise: Encrypted Storage Engine com KMIP. Ou Percona Server&lt;/td&gt;&lt;td&gt;&lt;code&gt;requireTLS&lt;/code&gt; no &lt;code&gt;mongod.&lt;wbr/&gt;conf&lt;/code&gt; e cliente com &lt;code&gt;tls=true&lt;/code&gt; e a CA&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Se for para guardar uma coisa deste post: criptografia em repouso e em trânsito são o mínimo, e hoje custam quase nada para ligar. Mas &lt;mark class=&quot;caneta-marca&quot;&gt;nenhuma das duas impede quem tem credencial de ler o dado&lt;/mark&gt;. Para isso você precisa de controle de acesso bem feito, auditoria e, nos casos mais sensíveis, criptografia em uso ou tokenização.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html&quot;&gt;Encrypting Amazon RDS resources&lt;/a&gt; (o que é cifrado, só na criação, o &lt;em&gt;grant&lt;/em&gt; na chave e o TDE do Oracle e do SQL Server como recurso à parte)&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CopySnapshot.html&quot;&gt;Copying a DB snapshot for Amazon RDS&lt;/a&gt; e &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/share-encrypted-snapshot.html&quot;&gt;Sharing encrypted snapshots&lt;/a&gt; (a cópia cifrada e a chave padrão que não se compartilha)&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_RenameInstance.html&quot;&gt;Renaming a DB instance&lt;/a&gt; e &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.Associating.html&quot;&gt;Associating a DB parameter group with a DB instance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS Prescriptive Guidance — &lt;a href=&quot;https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/encrypt-an-existing-amazon-rds-for-postgresql-db-instance.html&quot;&gt;Encrypt an existing Amazon RDS for PostgreSQL DB instance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2026/02/amazon-aurora-server-side-encryption-at-rest/&quot;&gt;Amazon Aurora now supports Server-Side Encryption by default&lt;/a&gt; e &lt;a href=&quot;https://aws.amazon.com/blogs/database/use-default-encryption-at-rest-for-new-amazon-aurora-clusters/&quot;&gt;Use default encryption at rest for new Amazon Aurora clusters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Concepts.General.SSL.html&quot;&gt;Using SSL with a PostgreSQL DB instance&lt;/a&gt; (&lt;code&gt;rds.&lt;wbr/&gt;force_ssl&lt;/code&gt;) e &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html&quot;&gt;Using SSL/TLS to encrypt a connection to a DB instance or cluster&lt;/a&gt; (o &lt;code&gt;global-bundle.&lt;wbr/&gt;pem&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;AWS KMS — &lt;a href=&quot;https://docs.aws.amazon.com/kms/latest/developerguide/kms-cryptography.html&quot;&gt;AWS KMS cryptography essentials&lt;/a&gt; (envelope encryption) e &lt;a href=&quot;https://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys.html&quot;&gt;Delete an AWS KMS key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Terraform — &lt;a href=&quot;https://github.com/hashicorp/terraform-provider-aws/blob/main/website/docs/r/db_instance.html.markdown&quot;&gt;aws_db_instance&lt;/a&gt; e &lt;a href=&quot;https://github.com/mongodb/terraform-provider-mongodbatlas/blob/master/docs/resources/encryption_at_rest.md&quot;&gt;mongodbatlas_encryption_at_rest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microsoft — &lt;a href=&quot;https://learn.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption&quot;&gt;Transparent Data Encryption (TDE)&lt;/a&gt; e Oracle — &lt;a href=&quot;https://docs.oracle.com/en/database/oracle/oracle-database/19/asoag/introduction-to-transparent-data-encryption.html&quot;&gt;Introduction to Transparent Data Encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PCI SSC — &lt;a href=&quot;https://listings.pcisecuritystandards.org/documents/PCI-DSS-v3-2-1-to-v4-0-Summary-of-Changes-r1.pdf&quot;&gt;PCI DSS: Summary of Changes from v3.2.1 to v4.0&lt;/a&gt; (requisito 3.5.1.2)&lt;/li&gt;
&lt;li&gt;Presidência da República — &lt;a href=&quot;https://www.planalto.gov.br/ccivil_03/_ato2015-2018/2018/lei/l13709compilado.htm&quot;&gt;Lei nº 13.709/2018, a LGPD&lt;/a&gt; (arts. 46 e 48)&lt;/li&gt;
&lt;li&gt;Banco Central — &lt;a href=&quot;https://www.bcb.gov.br/content/about/legislation_norms_docs/CMN_Resolution_No_4,893_2021.pdf&quot;&gt;Resolução CMN 4.893/2021&lt;/a&gt; (art. 3º, versão oficial em inglês)&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/libpq-ssl.html&quot;&gt;SSL Support (libpq)&lt;/a&gt; e &lt;a href=&quot;https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE&quot;&gt;&lt;code&gt;sslmode&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/ssl-tcp.html&quot;&gt;Secure TCP/IP Connections with SSL&lt;/a&gt;, &lt;a href=&quot;https://www.postgresql.org/docs/current/runtime-config-connection.html#RUNTIME-CONFIG-CONNECTION-SSL&quot;&gt;parâmetros de SSL&lt;/a&gt; e &lt;a href=&quot;https://www.postgresql.org/docs/current/auth-pg-hba-conf.html&quot;&gt;The pg_hba.conf File&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-SSL-VIEW&quot;&gt;pg_stat_ssl&lt;/a&gt;, &lt;a href=&quot;https://www.postgresql.org/docs/current/encryption-options.html&quot;&gt;Encryption Options&lt;/a&gt; e &lt;a href=&quot;https://www.postgresql.org/docs/current/pgcrypto.html#PGCRYPTO-NOTES-SEC-LIMITS&quot;&gt;pgcrypto: Security Limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;pgJDBC — &lt;a href=&quot;https://jdbc.postgresql.org/documentation/use/&quot;&gt;Initializing the Driver&lt;/a&gt; (o &lt;code&gt;sslmode&lt;/code&gt; padrão) e &lt;a href=&quot;https://jdbc.postgresql.org/documentation/ssl/&quot;&gt;Using SSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Percona — &lt;a href=&quot;https://docs.percona.com/pg-tde/index.html&quot;&gt;pg_tde&lt;/a&gt;, &lt;a href=&quot;https://docs.percona.com/pg-tde/global-key-provider-configuration/overview.html&quot;&gt;provedores de chaves&lt;/a&gt; e &lt;a href=&quot;https://docs.percona.com/pg-tde/index/tde-limitations.html&quot;&gt;limitações&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;EDB — &lt;a href=&quot;https://www.enterprisedb.com/docs/tde/latest/&quot;&gt;Transparent Data Encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;pgBackRest — &lt;a href=&quot;https://pgbackrest.org/configuration.html&quot;&gt;Configuration Reference&lt;/a&gt; (&lt;code&gt;repo-cipher-type&lt;/code&gt; e &lt;code&gt;repo-cipher-pass&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gitlab.com/cryptsetup/cryptsetup&quot;&gt;cryptsetup (LUKS)&lt;/a&gt; e &lt;a href=&quot;https://github.com/latchset/clevis&quot;&gt;Clevis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MongoDB Atlas — &lt;a href=&quot;https://www.mongodb.com/docs/atlas/security-kms-encryption/&quot;&gt;Encryption at Rest using Customer Key Management&lt;/a&gt;, &lt;a href=&quot;https://www.mongodb.com/docs/atlas/security-aws-kms/&quot;&gt;Manage Customer Keys with AWS KMS&lt;/a&gt; e &lt;a href=&quot;https://www.mongodb.com/docs/atlas/reference/faq/security/&quot;&gt;FAQ: Security&lt;/a&gt; (TLS obrigatório, só 1.2 e 1.3)&lt;/li&gt;
&lt;li&gt;MongoDB — &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/connection-string-formats/&quot;&gt;Connection String Formats&lt;/a&gt;, &lt;a href=&quot;https://www.mongodb.com/docs/manual/tutorial/configure-ssl/&quot;&gt;Configure MongoDB Instances for TLS/SSL Encryption&lt;/a&gt; e &lt;a href=&quot;https://www.mongodb.com/docs/manual/tutorial/upgrade-cluster-to-ssl/&quot;&gt;Upgrade a Cluster to Use TLS/SSL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MongoDB — &lt;a href=&quot;https://www.mongodb.com/docs/manual/core/security-encryption-at-rest/&quot;&gt;Encryption at Rest&lt;/a&gt; e &lt;a href=&quot;https://www.mongodb.com/docs/manual/tutorial/configure-encryption/&quot;&gt;Configure Encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Percona — &lt;a href=&quot;https://docs.percona.com/percona-server-for-mongodb/8.0/data-at-rest-encryption.html&quot;&gt;Percona Server for MongoDB: data at rest encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MongoDB — &lt;a href=&quot;https://www.mongodb.com/docs/manual/core/queryable-encryption/&quot;&gt;Queryable Encryption&lt;/a&gt;, &lt;a href=&quot;https://www.mongodb.com/docs/manual/core/queryable-encryption/reference/compatibility/&quot;&gt;compatibilidade&lt;/a&gt; e &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/method/BinData/&quot;&gt;BinData (subtipos)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html&quot;&gt;What is Nitro Enclaves?&lt;/a&gt; e &lt;a href=&quot;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sev-snp.html&quot;&gt;AMD SEV-SNP for Amazon EC2 instances&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Intel — &lt;a href=&quot;https://cdrdv2-public.intel.com/690419/TDX-Whitepaper-February2022.pdf&quot;&gt;Intel Trust Domain Extensions (white paper)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Segurança</category><category>Criptografia</category><category>Banco de Dados</category><category>AWS</category></item><item><title>Filtros de serialização no Jackson — mascarando número de cartão nos logs</title><link>https://blog.cesarschutz.com.br/posts/jackson-filtros-mascarando-cartao/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/jackson-filtros-mascarando-cartao/</guid><description>Como usar @JsonFilter, PropertyFilter e um mixin em Object para mascarar o número do cartão e remover o CVV só no mapper de log, com a API ainda devolvendo tudo.</description><pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Logar o payload de uma requisição ou de um evento é uma das formas mais práticas de investigar problemas. Num sistema de cartões, o risco é óbvio: o JSON que vai pro log carrega número do cartão, CVV, CPF. Ao mesmo tempo, a resposta da API precisa continuar trazendo &lt;span class=&quot;caneta caneta-duplo&quot;&gt;esses dados completos&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;O Jackson resolve isso com &lt;strong&gt;filtros de serialização&lt;/strong&gt;, um mecanismo que deixa você decidir, campo a campo, o que é escrito no JSON, &lt;mark class=&quot;caneta-marca&quot;&gt;sem alterar as classes e sem mexer no mapper usado pela API&lt;/mark&gt;.&lt;/p&gt;
&lt;aside class=&quot;aviso&quot; data-aviso=&quot;nota&quot; aria-label=&quot;Nota&quot;&gt;&lt;div class=&quot;aviso-corpo&quot;&gt;&lt;p&gt;&lt;strong class=&quot;aviso-rotulo&quot;&gt;Nota.&lt;/strong&gt; Os exemplos usam &lt;strong&gt;Jackson 3&lt;/strong&gt; (pacote &lt;code&gt;tools.&lt;wbr/&gt;jackson&lt;/code&gt;, o que vem no &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Release-Notes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Spring Boot&lt;/span&gt; 4). No fim há uma tabela com o que muda no Jackson 2. Todo o código foi compilado e executado com Jackson 3.2.3 (e a versão adaptada com Jackson 2.21.0); as saídas mostradas são as reais.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;1-as-três-peças&quot;&gt;1. As três peças&lt;/h2&gt;
&lt;p&gt;Um filtro envolve &lt;span class=&quot;caneta caneta-explica&quot;&gt;&lt;span class=&quot;caneta-explica-alvo&quot;&gt;três coisas&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-explica-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (quer dizer: &lt;/span&gt;nome, regra e registro&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, e vale entender cada uma antes do código.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;@JsonFilter(&amp;quot;id&amp;quot;)&lt;/code&gt;&lt;/strong&gt; é uma etiqueta colocada na classe. Ela diz ao Jackson: “quando for serializar esta classe, passe cada campo pelo filtro chamado &lt;em&gt;id&lt;/em&gt;”. A anotação não diz &lt;em&gt;qual&lt;/em&gt; é o filtro, &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;só o nome dele&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;PropertyFilter&lt;/code&gt;&lt;/strong&gt; é o filtro em si, a regra. O Jackson chama o filtro uma vez para cada propriedade do objeto, e o filtro decide o que fazer: escrever normalmente, omitir, ou escrever outra coisa no lugar. Na prática você estende &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;SimpleBeanPropertyFilter&lt;/code&gt;&lt;/span&gt;, que já traz o comportamento padrão.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;FilterProvider&lt;/code&gt;&lt;/strong&gt; é o registro, configurado no mapper, que liga o nome ao filtro. A implementação padrão é &lt;code&gt;SimpleFilterProvider&lt;/code&gt;, usada com &lt;code&gt;addFilter(&amp;quot;id&amp;quot;, filtro)&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-colchete&quot;&gt;&lt;p&gt;A consequência dessa separação é que a mesma classe pode ser serializada com filtros diferentes, dependendo do mapper que está sendo usado.&lt;/p&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-primeiro-exemplo-removendo-o-cvv&quot;&gt;2. Primeiro exemplo: removendo o CVV&lt;/h2&gt;
&lt;p&gt;O caso mais simples usa um filtro pronto do Jackson:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Cartao.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;fasterxml&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@JsonFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&lt;span class=&quot;caneta-codigo-circulo&quot;&gt;cartaoFilter&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;o provider precisa ter este id&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cvv&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:10&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SimpleBeanPropertyFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; mapper &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;filterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;cartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SimpleBeanPropertyFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;serializeAllExcept&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;cvv&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5502091234567890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;123&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Saída:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5502091234567890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code&gt;SimpleBeanPropertyFilter&lt;/code&gt; tem quatro filtros prontos: &lt;code&gt;serializeAll()&lt;/code&gt; não filtra nada, &lt;code&gt;serializeAllExcept(...)&lt;/code&gt; escreve tudo menos os campos listados, &lt;span class=&quot;caneta caneta-circulo longo&quot;&gt;&lt;code&gt;filterOutAllExcept(...)&lt;/code&gt;&lt;/span&gt; escreve só os campos listados e &lt;code&gt;filterOutAll()&lt;/code&gt; não escreve nenhum.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;caneta-aparte&quot;&gt;Também dá para passar o provider só na hora de escrever, sem configurá-lo no mapper&lt;/span&gt;: &lt;code&gt;mapper.&lt;wbr/&gt;writer(filterProvider).&lt;wbr/&gt;writeValueAsString(objeto)&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;o-efeito-colateral-de-anotar-a-classe&quot;&gt;O efeito colateral de anotar a classe&lt;/h3&gt;
&lt;p&gt;Com &lt;code&gt;@JsonFilter&lt;/code&gt; na classe, &lt;strong&gt;todo&lt;/strong&gt; mapper que serializar essa classe &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;precisa conhecer o filtro&lt;/span&gt;. Um mapper sem provider falha:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot; style=&quot;--linhas:2&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;txt&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;tools.jackson.databind.exc.InvalidDefinitionException:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Cannot resolve PropertyFilter with id &amp;#39;cartaoFilter&amp;#39;; no FilterProvider configured&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Ou seja, se o mapper da API não tiver o filtro registrado, a anotação quebra a API. Guarde isso: é o motivo de existir o mixin da seção 4.&lt;/p&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-mascarando-o-número-do-cartão&quot;&gt;3. Mascarando o número do cartão&lt;/h2&gt;
&lt;p&gt;Remover campo é fácil com os filtros prontos. Para &lt;strong&gt;mascarar&lt;/strong&gt;, você escreve um filtro próprio e sobrescreve &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;serializeAsProperty&lt;/code&gt;&lt;/span&gt;, o método que o Jackson chama para cada propriedade:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:57&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;MascaraCartaoFilter.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonGenerator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SerializationContext&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BeanPropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jdk&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;MapProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SimpleBeanPropertyFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;MascaraCartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;SimpleBeanPropertyFilter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CAMPOS_MASCARADOS &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Set&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;numeroCartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pan&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CAMPOS_REMOVIDOS &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Set&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;cvv&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;senha&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Override&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; serializeAsProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonGenerator&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SerializationContext&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ctxt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; nome &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getName&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 1. Campo proibido: não escreve nada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CAMPOS_REMOVIDOS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;contains&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;nome&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;serializeAsOmittedProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ctxt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 2. Campo sensível: escreve a versão mascarada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CAMPOS_MASCARADOS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;contains&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;nome&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valorDe&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writeStringProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;nome&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; mascarar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 3. Qualquer outro campo: segue o fluxo normal&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;serializeAsProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ctxt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valorDe&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BeanPropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; propriedade&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; propriedade&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// campo de um objeto/record&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;MapProperty&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entrada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entrada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getValue&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;             &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// entrada de um Map&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; mascarar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; digitos &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;replaceAll&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;digitos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;repeat&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;digitos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:3&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; digitos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;substring&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;repeat&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;digitos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; digitos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;substring&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;digitos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;6 primeiros e 4 últimos: PCI ok&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Cada propriedade do &lt;code&gt;Cartao&lt;/code&gt; passa pelo filtro, uma de cada vez. Na lousa, a caneta sublinha a propriedade da vez e desenha o caminho que ela toma até o JSON do log. Aperte o play, arraste sobre a lousa ou clique num passo da lista:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lousa: um Cartao com titular, numero e cvv passa pelo MascaraCartaoFilter, uma propriedade por vez. O cvv é omitido, o numero sai mascarado como 550209******7890 e o titular segue o fluxo normal para o JSON do log.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/jackson-filtros-mascarando-cartao/&quot;&gt;A lousa interativa está no site.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;O método &lt;code&gt;valorDe&lt;/code&gt; trata dois tipos de &lt;code&gt;writer&lt;/code&gt;: &lt;code&gt;BeanPropertyWriter&lt;/code&gt; para campos de objetos e records, e &lt;code&gt;MapProperty&lt;/code&gt; para entradas de um &lt;code&gt;Map&lt;/code&gt; (&lt;mark class=&quot;caneta-grifo&quot;&gt;o filtro também é aplicado a mapas&lt;/mark&gt;, como aparece na seção 4). A função &lt;code&gt;mascarar&lt;/code&gt; remove espaços e hífens, mantém os 6 primeiros e os 4 últimos dígitos e, se o valor for curto demais para ser um número de cartão, mascara tudo.&lt;/p&gt;
&lt;p&gt;O registro é o mesmo de antes, usando o &lt;code&gt;Cartao&lt;/code&gt; anotado com &lt;code&gt;@JsonFilter(&amp;quot;cartaoFilter&amp;quot;)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:6&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; mapper &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;filterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;cartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MascaraCartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5502 0912 3456 7890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;123&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Saída:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;550209******7890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Se o número vier &lt;code&gt;null&lt;/code&gt;, &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;o filtro não inventa nada&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;null continua null&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; e segue o fluxo normal: &lt;code&gt;{&amp;quot;titular&amp;quot;:&amp;quot;Cesar&amp;quot;,&amp;quot;numero&amp;quot;:null}&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;4-aplicando-em-todas-as-classes-com-mixin&quot;&gt;4. Aplicando em todas as classes com mixin&lt;/h2&gt;
&lt;p&gt;Anotar cada DTO com &lt;code&gt;@JsonFilter&lt;/code&gt; tem dois problemas: é fácil esquecer uma classe e, como vimos, a anotação obriga todo mapper a conhecer o filtro.&lt;/p&gt;
&lt;div class=&quot;caneta-moldura&quot;&gt;&lt;p&gt;O &lt;strong&gt;mixin&lt;/strong&gt; resolve os dois. Mixin é o recurso do Jackson para “colar” anotações numa classe sem alterar o código dela. Você cria uma classe auxiliar só com as anotações e registra no mapper com &lt;code&gt;addMixIn(alvo, classeComAsAnotacoes)&lt;/code&gt;. Aquele mapper passa a tratar o alvo como se tivesse aquelas anotações; os outros mappers não enxergam nada.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;O truque é usar &lt;code&gt;Object.&lt;wbr/&gt;class&lt;/code&gt; como alvo. Toda classe herda de &lt;code&gt;Object&lt;/code&gt;, e o Jackson considera os mixins de &lt;code&gt;Object&lt;/code&gt; ao ler as anotações de qualquer classe. Resultado: &lt;mark class=&quot;caneta-marca&quot;&gt;toda classe ganha o &lt;code&gt;@JsonFilter&lt;/code&gt;, mas só dentro deste mapper&lt;/mark&gt;.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;LogFilterMixin.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;fasterxml&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@JsonFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;logFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;abstract&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;LogFilterMixin&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:1&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addMixIn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LogFilterMixin&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;Object: vale para toda classe&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;filterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;logFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MascaraCartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Agora as classes de domínio não precisam de nenhuma anotação do Jackson:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cvv&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Cliente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; nome&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cpf&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Pedido&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Cliente&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cliente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Cartao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                     &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Cartao&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; adicionais&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Map&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Object&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; extras&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O mesmo pedido serializado pelos dois mappers:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:11&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;jsonc&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;jsonc&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// mapper normal (API)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cliente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;nome&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cpf&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;123.456.789-00&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5502091234567890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cvv&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;123&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;adicionais&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:[{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Maria&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;4000123412341234&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cvv&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;999&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;extras&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;4111111111111111&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// logMapper&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cliente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;nome&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cpf&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;123.456.789-00&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Cesar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;550209******7890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;adicionais&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:[{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Maria&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;400012******1234&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:1&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;extras&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;411111******1111&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;até a entrada do Map&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O filtro alcançou o objeto aninhado, os itens da lista e a entrada do &lt;code&gt;Map&lt;/code&gt;. O mapper normal continuou escrevendo tudo.&lt;/p&gt;
&lt;h2 id=&quot;5-juntando-tudo-no-spring&quot;&gt;5. Juntando tudo no Spring&lt;/h2&gt;
&lt;p&gt;Na aplicação, isso vira dois beans: o mapper padrão, marcado como &lt;code&gt;@Primary&lt;/code&gt;, e o mapper de log.&lt;/p&gt;
&lt;p&gt;A figura mostra o caminho de um mesmo pedido pelos dois. No de cima, o &lt;code&gt;@Primary&lt;/code&gt;, ele sai inteiro na resposta da API. No &lt;code&gt;logMapper&lt;/code&gt;, passa pelas três peças, na ordem dos números: o mixin em &lt;code&gt;Object&lt;/code&gt; dá à classe o &lt;code&gt;@JsonFilter(&amp;quot;logFilter&amp;quot;)&lt;/code&gt; (1), o &lt;code&gt;FilterProvider&lt;/code&gt; liga esse nome ao &lt;code&gt;MascaraCartaoFilter&lt;/code&gt; (2), e o filtro decide campo a campo (3). O JSON do log sai com o número mascarado e sem o CVV (4). Os pontos que correm pelas setas seguem essa ordem; com o mouse numa cor da legenda, a figura destaca só aquela peça.&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 720&quot;
  aria-label=&quot;Diagrama dos dois mappers: o mesmo pedido vai para o objectMapper, que escreve tudo na resposta da API, e para o logMapper, onde passa pelo mixin, pelo FilterProvider e pelo MascaraCartaoFilter e sai no log mascarado e sem o CVV.&quot;&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;tom-azul&quot;&gt;
      &lt;rect x=&quot;37&quot; y=&quot;257&quot; width=&quot;280&quot; height=&quot;200&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;250&quot; width=&quot;280&quot; height=&quot;200&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;250&quot; width=&quot;280&quot; height=&quot;200&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M170 250 V116 C 170 106 176 100 186 100 H396 M382 91 L396 100 L382 109&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;

    &lt;g class=&quot;tom-petroleo&quot;&gt;
      &lt;rect x=&quot;400&quot; y=&quot;30&quot; width=&quot;300&quot; height=&quot;140&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;400&quot; y=&quot;30&quot; width=&quot;300&quot; height=&quot;140&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;400&quot; y=&quot;30&quot; width=&quot;300&quot; height=&quot;140&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M700 100 H772 M758 91 L772 100 L758 109&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;rect x=&quot;360&quot; y=&quot;200&quot; width=&quot;460&quot; height=&quot;465&quot; rx=&quot;16&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;360&quot; y=&quot;200&quot; width=&quot;460&quot; height=&quot;465&quot; rx=&quot;16&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-azul&quot;&gt;
      &lt;path d=&quot;M310 335 H386 M372 326 L386 335 L372 344&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;

    &lt;g class=&quot;tom-petroleo&quot;&gt;
      &lt;rect x=&quot;787&quot; y=&quot;37&quot; width=&quot;380&quot; height=&quot;140&quot; rx=&quot;10&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;780&quot; y=&quot;30&quot; width=&quot;380&quot; height=&quot;140&quot; rx=&quot;10&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;780&quot; y=&quot;30&quot; width=&quot;380&quot; height=&quot;140&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;

    &lt;g class=&quot;tom-ambar&quot;&gt;
      &lt;rect x=&quot;390&quot; y=&quot;280&quot; width=&quot;400&quot; height=&quot;90&quot; rx=&quot;10&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;390&quot; y=&quot;280&quot; width=&quot;400&quot; height=&quot;90&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M590 370 V404 M581 392 L590 406 L599 392&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;
      &lt;rect x=&quot;390&quot; y=&quot;410&quot; width=&quot;400&quot; height=&quot;90&quot; rx=&quot;10&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;390&quot; y=&quot;410&quot; width=&quot;400&quot; height=&quot;90&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M590 500 V534 M581 522 L590 536 L599 522&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-verde&quot;&gt;
      &lt;rect x=&quot;390&quot; y=&quot;540&quot; width=&quot;400&quot; height=&quot;90&quot; rx=&quot;10&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;390&quot; y=&quot;540&quot; width=&quot;400&quot; height=&quot;90&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M790 585 H862 M848 576 L862 585 L848 594&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;

    &lt;g class=&quot;tom-verde&quot;&gt;
      &lt;rect x=&quot;875&quot; y=&quot;477&quot; width=&quot;285&quot; height=&quot;170&quot; rx=&quot;10&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;868&quot; y=&quot;470&quot; width=&quot;285&quot; height=&quot;170&quot; rx=&quot;10&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;868&quot; y=&quot;470&quot; width=&quot;285&quot; height=&quot;170&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;path d=&quot;M170 246 V116 C 170 106 176 100 186 100 H390&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
    &lt;path d=&quot;M314 335 H380&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;
    &lt;path d=&quot;M704 100 H766&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-2&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;path d=&quot;M590 374 V400&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-3&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;path d=&quot;M590 504 V530&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-4&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;path d=&quot;M794 585 H856&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-5&quot;/&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;g transform=&quot;translate(236 258) scale(0.56)&quot; class=&quot;marca marca-java&quot;&gt;&lt;g class=&quot;tinta tom-ambar&quot;&gt;
    &lt;path d=&quot;M38 39 C 31 33 44 27 37 20 C 32 15 37 10 41 7&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M55 39 C 48 33 61 27 54 20 C 50 16 53 12 56 10&quot; class=&quot;linha-tom&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M17 46 H73 V60 C73 75 62 84 45 84 C28 84 17 75 17 60 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M17 46 H73 V60 C73 75 62 84 45 84 C28 84 17 75 17 60 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M73 51 C 88 49 90 68 71 70&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M9 91 C 30 98 62 98 83 91&quot; class=&quot;linha-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;
    &lt;g transform=&quot;translate(638 42) scale(0.5)&quot; class=&quot;marca marca-spring&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
    &lt;g transform=&quot;translate(758 212) scale(0.5)&quot; class=&quot;marca marca-spring&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;text x=&quot;50&quot; y=&quot;296&quot; class=&quot;titulo-caixa&quot;&gt;Pedido&lt;/text&gt;
    &lt;text x=&quot;50&quot; y=&quot;340&quot; class=&quot;texto-caixa&quot;&gt;cartao:&lt;/text&gt;
    &lt;text x=&quot;50&quot; y=&quot;386&quot; class=&quot;codigo&quot;&gt;5502091234567890&lt;/text&gt;
    &lt;text x=&quot;50&quot; y=&quot;426&quot; class=&quot;codigo&quot;&gt;cvv 123&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;
    &lt;text x=&quot;420&quot; y=&quot;90&quot; class=&quot;titulo-caixa&quot;&gt;objectMapper&lt;/text&gt;
    &lt;text x=&quot;420&quot; y=&quot;134&quot; class=&quot;texto-caixa&quot;&gt;@Primary: a API&lt;/text&gt;
    &lt;text x=&quot;384&quot; y=&quot;248&quot; class=&quot;titulo-caixa&quot;&gt;logMapper&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;
    &lt;text x=&quot;800&quot; y=&quot;78&quot; class=&quot;titulo-caixa&quot;&gt;Resposta da API&lt;/text&gt;
    &lt;text x=&quot;800&quot; y=&quot;122&quot; class=&quot;codigo&quot;&gt;5502091234567890&lt;/text&gt;
    &lt;text x=&quot;800&quot; y=&quot;156&quot; class=&quot;codigo&quot;&gt;cvv 123&lt;/text&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;circle cx=&quot;762&quot; cy=&quot;306&quot; r=&quot;18&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;762&quot; y=&quot;307&quot; class=&quot;selo-texto&quot;&gt;1&lt;/text&gt;
    &lt;text x=&quot;410&quot; y=&quot;316&quot; class=&quot;titulo-caixa&quot;&gt;mixin em Object&lt;/text&gt;
    &lt;text x=&quot;410&quot; y=&quot;352&quot; class=&quot;codigo&quot;&gt;@JsonFilter(&quot;logFilter&quot;)&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;circle cx=&quot;762&quot; cy=&quot;436&quot; r=&quot;18&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;762&quot; y=&quot;437&quot; class=&quot;selo-texto&quot;&gt;2&lt;/text&gt;
    &lt;text x=&quot;410&quot; y=&quot;446&quot; class=&quot;titulo-caixa&quot;&gt;FilterProvider&lt;/text&gt;
    &lt;text x=&quot;410&quot; y=&quot;482&quot; class=&quot;texto-caixa&quot;&gt;liga &quot;logFilter&quot; ao filtro&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;circle cx=&quot;762&quot; cy=&quot;566&quot; r=&quot;18&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;762&quot; y=&quot;567&quot; class=&quot;selo-texto&quot;&gt;3&lt;/text&gt;
    &lt;text x=&quot;410&quot; y=&quot;576&quot; class=&quot;titulo-caixa&quot;&gt;MascaraCartaoFilter&lt;/text&gt;
    &lt;text x=&quot;410&quot; y=&quot;612&quot; class=&quot;texto-caixa&quot;&gt;remove, mascara ou segue&lt;/text&gt;
    &lt;circle cx=&quot;1126&quot; cy=&quot;496&quot; r=&quot;18&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;1126&quot; y=&quot;497&quot; class=&quot;selo-texto&quot;&gt;4&lt;/text&gt;
    &lt;text x=&quot;888&quot; y=&quot;512&quot; class=&quot;titulo-caixa&quot;&gt;JSON do log&lt;/text&gt;
    &lt;text x=&quot;888&quot; y=&quot;562&quot; class=&quot;codigo texto-tom&quot;&gt;550209******7890&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-vermelho tom-verde&quot;&gt;
    &lt;text x=&quot;888&quot; y=&quot;606&quot; class=&quot;nota-pequena texto-tom&quot;&gt;sem o cvv&lt;/text&gt;
  &lt;/g&gt;

  &lt;g class=&quot;legenda tom-azul&quot;&gt;&lt;rect x=&quot;40&quot; y=&quot;686&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;72&quot; y=&quot;700&quot; class=&quot;nota-pequena&quot;&gt;pedido&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-petroleo&quot;&gt;&lt;rect x=&quot;190&quot; y=&quot;686&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;222&quot; y=&quot;700&quot; class=&quot;nota-pequena&quot;&gt;mappers&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-ambar&quot;&gt;&lt;rect x=&quot;350&quot; y=&quot;686&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;382&quot; y=&quot;700&quot; class=&quot;nota-pequena&quot;&gt;mixin&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-roxo&quot;&gt;&lt;rect x=&quot;480&quot; y=&quot;686&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;512&quot; y=&quot;700&quot; class=&quot;nota-pequena&quot;&gt;provider&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-verde&quot;&gt;&lt;rect x=&quot;640&quot; y=&quot;686&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;672&quot; y=&quot;700&quot; class=&quot;nota-pequena&quot;&gt;filtro&lt;/text&gt;&lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;Cada cor é uma peça: o pedido (azul), os dois mappers (petróleo), o mixin (âmbar), o provider (roxo) e o filtro (verde), que entrega ao log o número mascarado.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:32&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;JacksonConfig.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Bean&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Configuration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Primary&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DeserializationFeature&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cfg&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DateTimeFeature&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ser&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Configuration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;JacksonConfig&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Primary&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; objectMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; baseBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; baseBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addMixIn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LogFilterMixin&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;filterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;logFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MascaraCartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Builder&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; baseBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;disable&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DeserializationFeature&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;FAIL_ON_UNKNOWN_PROPERTIES&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;disable&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DateTimeFeature&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;WRITE_DATES_AS_TIMESTAMPS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code&gt;@Primary&lt;/code&gt; é o que o Spring injeta quando ninguém especifica qual mapper quer, então é ele que serializa as requisições e respostas HTTP. O &lt;code&gt;logMapper&lt;/code&gt; só é usado onde for pedido pelo nome (o nome do bean é o nome do método). O &lt;code&gt;baseBuilder()&lt;/code&gt; evita repetir a configuração comum nos dois.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Não pule o mapper &lt;code&gt;@Primary&lt;/code&gt;: o Spring Boot só cria o mapper padrão dele quando a aplicação não declara nenhum bean desse tipo. Se você declarar apenas o &lt;code&gt;logMapper&lt;/code&gt;, ele vira o único mapper da aplicação e passa a ser usado também nas respostas da API, que começam a devolver cartão mascarado.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-carimbado&quot;&gt;&lt;p&gt;A documentação do Spring Boot diz as duas coisas: o &lt;code&gt;JsonMapper&lt;/code&gt; declarado substitui o padrão e deve ser marcado como &lt;code&gt;@Primary&lt;/code&gt;, e declará-lo desliga toda a configuração automática do mapper.&lt;/p&gt;&lt;p class=&quot;caneta-carimbo&quot;&gt;&lt;span class=&quot;caneta-carimbo-selo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt;Carimbo: &lt;/span&gt;conferido na doc do Spring Boot&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;
&lt;figure class=&quot;evidencia&quot; data-astro-cid-zafmdbgc&gt;&lt;a class=&quot;evidencia-imagem&quot; href=&quot;https://docs.spring.io/spring-boot/how-to/spring-mvc.html#howto.spring-mvc.customize-jackson-jsonmapper&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-astro-cid-zafmdbgc&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/_astro/spring-jsonmapper.E0c3vvIf_18HOxB.webp&quot; srcset=&quot;/_astro/spring-jsonmapper.E0c3vvIf_2wICjd.webp 640w, /_astro/spring-jsonmapper.E0c3vvIf_ZP1qE4.webp 1120w, /_astro/spring-jsonmapper.E0c3vvIf_18HOxB.webp 1408w&quot; alt=&quot;Trecho da documentação do Spring Boot: para substituir o JsonMapper padrão, declare um @Bean desse tipo, de preferência com @Primary, e isso desliga toda a configuração automática do JsonMapper.&quot; sizes=&quot;(max-width: 760px) 100vw, 760px&quot; data-astro-cid-zafmdbgc=&quot;true&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1408&quot; height=&quot;424&quot;&gt;&lt;/a&gt;&lt;figcaption data-astro-cid-zafmdbgc&gt;Documentação do Spring Boot, Customize the Jackson JsonMapper · &lt;a href=&quot;https://docs.spring.io/spring-boot/how-to/spring-mvc.html#howto.spring-mvc.customize-jackson-jsonmapper&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-astro-cid-zafmdbgc&gt;docs.spring.io&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&quot;caneta-margem caneta-visto&quot;&gt;&lt;p&gt;Um detalhe do &lt;code&gt;baseBuilder()&lt;/code&gt;: como ele parte de &lt;code&gt;JsonMapper.&lt;wbr/&gt;builder()&lt;/code&gt;, as propriedades &lt;code&gt;spring.&lt;wbr/&gt;jackson.*&lt;/code&gt; do &lt;code&gt;application.&lt;wbr/&gt;yml&lt;/code&gt; não valem para nenhum dos dois mappers (declarar um &lt;code&gt;JsonMapper&lt;/code&gt; próprio desliga toda a configuração automática do mapper). Se a aplicação depende delas, receba o &lt;code&gt;JsonMapper.&lt;wbr/&gt;Builder&lt;/code&gt; que o Spring Boot oferece. Ele já vem com as &lt;code&gt;spring.&lt;wbr/&gt;jackson.*&lt;/code&gt; aplicadas e é criado de novo a cada injeção, então o mixin do &lt;code&gt;logMapper&lt;/code&gt; não vaza para o mapper da API:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:14&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;JacksonConfig.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Primary&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; objectMapper&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Builder builder&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Builder builder&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; builder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addMixIn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LogFilterMixin&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;filterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SimpleFilterProvider&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;logFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MascaraCartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para usar o mapper de log, vale centralizar num componente:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:23&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;LogJson.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;beans&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;factory&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Qualifier&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;stereotype&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Component&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JacksonException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;tools&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jackson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;databind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Component&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;LogJson&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LogJson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Qualifier&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;logMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonMapper&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;logMapper &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; toJson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; objeto&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writeValueAsString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;objeto&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JacksonException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:2&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// nunca cair no toString() aqui: ele não passa pelo filtro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&amp;lt;falha ao serializar &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; objeto&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getClass&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getSimpleName&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;só o nome da classe vai pro log&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;E no código:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;info&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Pedido recebido: {}&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; logJson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toJson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pedido&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;6-variação-marcar-os-campos-com-uma-anotação-própria&quot;&gt;6. Variação: marcar os campos com uma anotação própria&lt;/h2&gt;
&lt;div class=&quot;caneta-margem caneta-pergunta&quot;&gt;&lt;p&gt;Filtrar pelo nome do campo tem um ponto fraco: &lt;code&gt;numero&lt;/code&gt; é um nome genérico. O número da conta ou o número do endereço também seriam mascarados, e um campo de cartão com outro nome (&lt;code&gt;cartaoVinculado&lt;/code&gt;, por exemplo) escaparia.&lt;/p&gt;&lt;p class=&quot;caneta-escrita caneta-pergunta-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt;Pergunta do leitor: &lt;/span&gt;como marcar só o que é cartão?&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Uma alternativa é criar uma anotação sua (não do Jackson) e fazer o filtro procurar por ela:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:6&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;NumeroCartao.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Retention&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;RetentionPolicy&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:1&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Retention&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;RetentionPolicy&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;RUNTIME&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;sem isso, o filtro não enxerga&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; NumeroCartao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:16&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;MascaraPorAnotacaoFilter.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;MascaraPorAnotacaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;SimpleBeanPropertyFilter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Override&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; serializeAsProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JsonGenerator&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SerializationContext&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ctxt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getAnnotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;NumeroCartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;null&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; writer &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BeanPropertyWriter&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; propriedade&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; propriedade&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writeStringProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getName&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MascaraCartaoFilter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mascarar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;serializeAsProperty&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pojo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; g&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ctxt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:8&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Cartao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; titular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@NumeroCartao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Conta&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@NumeroCartao&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cartaoVinculado&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// número da conta: não deve ser mascarado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// getters...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Saída de uma &lt;code&gt;Conta&lt;/code&gt; pelo mapper de log:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cartaoVinculado&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;550209******7890&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;12345-6&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A troca é que agora os DTOs precisam da anotação. A diferença para o &lt;code&gt;@JsonFilter&lt;/code&gt; é que uma anotação própria &lt;span class=&quot;caneta caneta-duplo&quot;&gt;não quebra os outros mappers&lt;/span&gt;, porque eles simplesmente a ignoram. Também dá para combinar as duas abordagens (lista de nomes e anotação) no mesmo filtro. Só lembre que entradas de &lt;code&gt;Map&lt;/code&gt; não têm anotação, então essa variação vale apenas para campos de objetos e records.&lt;/p&gt;
&lt;h2 id=&quot;7-cuidados&quot;&gt;7. Cuidados&lt;/h2&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;&lt;strong&gt;O filtro só age quando o objeto passa pelo mapper.&lt;/strong&gt; Um &lt;code&gt;log.&lt;wbr/&gt;info(&amp;quot;{}&amp;quot;, pedido)&lt;/code&gt; usa o &lt;code&gt;toString()&lt;/code&gt;, e o &lt;code&gt;toString()&lt;/code&gt; de um &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://openjdk.org/jeps/395&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;record&lt;/span&gt; (ou de uma classe com &lt;code&gt;@Data&lt;/code&gt;/&lt;code&gt;@ToString&lt;/code&gt; do Lombok) imprime tudo:&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;txt&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;s class=&quot;caneta-codigo-riscado&quot; style=&quot;--recuo:0&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Cartao[titular=Cesar, numero=5502091234567890, cvv=123]&lt;/span&gt;&lt;/s&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;isso não pode ir pro log&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-postit&quot; role=&quot;note&quot;&gt;&lt;p class=&quot;caneta-escrita&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt;Lembrete: &lt;/span&gt;Por isso a regra é logar sempre via &lt;code&gt;logJson.&lt;wbr/&gt;toJson(...)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;A animação mostra os dois caminhos até o log e começa sozinha quando chega à tela. Primeiro, o &lt;code&gt;log.&lt;wbr/&gt;info(&amp;quot;{}&amp;quot;, pedido)&lt;/code&gt; leva o cartão direto ao log, sem passar pelo filtro: o número e o CVV chegam inteiros, e as duas linhas são riscadas, porque é isso que não pode ficar no log. Depois, o &lt;code&gt;logJson.&lt;wbr/&gt;toJson(pedido)&lt;/code&gt; leva o mesmo cartão pelo &lt;code&gt;MascaraCartaoFilter&lt;/code&gt;: o meio do número ganha uma fita, o CVV fica para trás, e o log recebe &lt;code&gt;550209******7890&lt;/code&gt;, escrito embaixo. Um clique na imagem pausa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que passa pelo filtro e o que não passa.&lt;/strong&gt; Com o mixin em &lt;code&gt;Object&lt;/code&gt;, passam objetos, records, objetos aninhados, itens de listas e entradas de &lt;code&gt;Map&lt;/code&gt; (a chave vira o nome da propriedade). Uma &lt;code&gt;String&lt;/code&gt; solta não passa, inclusive uma &lt;code&gt;String&lt;/code&gt; que já contém JSON: &lt;code&gt;logJson.&lt;wbr/&gt;toJson(&amp;quot;5502091234567890&amp;quot;)&lt;/code&gt; sai inteiro. Se o sistema loga &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;o corpo cru da requisição&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;comum em filtro de log HTTP&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; como texto, o filtro não protege.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Classes com &lt;code&gt;@JsonFilter&lt;/code&gt; próprio.&lt;/strong&gt; Uma anotação diretamente na classe &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;tem prioridade sobre o mixin&lt;/span&gt; de &lt;code&gt;Object&lt;/code&gt;. Se alguma classe tiver &lt;code&gt;@JsonFilter(&amp;quot;outroId&amp;quot;)&lt;/code&gt;, o &lt;code&gt;logMapper&lt;/code&gt; falha com &lt;code&gt;No filter configured with id &amp;#39;outroId&amp;#39;&lt;/code&gt;. A solução é registrar esse id também no provider ou definir um filtro padrão com &lt;code&gt;new SimpleFilterProvider().&lt;wbr/&gt;setDefaultFilter(filtro)&lt;/code&gt;, que é usado para qualquer id sem registro.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-asterisco&quot;&gt;&lt;p&gt;&lt;strong&gt;O filtro é compartilhado entre threads.&lt;/strong&gt; Uma única instância atende todas as serializações do mapper. Mantenha o filtro sem estado mutável, como no exemplo (conjuntos imutáveis e métodos que só dependem dos parâmetros).&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Só serialização.&lt;/strong&gt; Filtros não afetam a leitura de JSON. O &lt;code&gt;logMapper&lt;/code&gt; desserializa normalmente.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O tipo muda.&lt;/strong&gt; O campo mascarado &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;sempre sai como string&lt;/span&gt; no JSON, mesmo que o original seja numérico.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CVV não se mascara, se remove.&lt;/strong&gt; CVV não deve aparecer em log nenhum, nem parcialmente. Por isso o exemplo remove o campo em vez de mascará-lo. O PCI DSS proíbe guardar o código de verificação do cartão depois da autorização, mesmo cifrado, e &lt;mark class=&quot;caneta-grifo&quot;&gt;um log é um lugar onde ele fica guardado&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quantos dígitos mostrar.&lt;/strong&gt; O PCI DSS (requisito 3.4.1) limita o número exibido a, no máximo, o BIN e os 4 últimos dígitos. Como o BIN tem &lt;span class=&quot;caneta caneta-circulo longo&quot;&gt;de 6 a 8 dígitos&lt;/span&gt;, os 6 primeiros e os 4 últimos do &lt;code&gt;mascarar&lt;/code&gt; ficam dentro desse limite.&lt;/p&gt;
&lt;h2 id=&quot;8-jackson-2-x-jackson-3&quot;&gt;8. Jackson 2 x Jackson 3&lt;/h2&gt;
&lt;p&gt;A ideia é a mesma nas duas versões; mudam pacotes e nomes de métodos.&lt;/p&gt;

































































&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Jackson 3, Jackson 2&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Jackson 3&lt;/th&gt;&lt;th&gt;Jackson 2&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Pacote base&lt;/td&gt;&lt;td&gt;&lt;code&gt;tools.&lt;wbr/&gt;jackson.&lt;wbr/&gt;databind&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;com.&lt;wbr/&gt;fasterxml.&lt;wbr/&gt;jackson.&lt;wbr/&gt;databind&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@JsonFilter&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;com.&lt;wbr/&gt;fasterxml.&lt;wbr/&gt;jackson.&lt;wbr/&gt;annotation&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;com.&lt;wbr/&gt;fasterxml.&lt;wbr/&gt;jackson.&lt;wbr/&gt;annotation&lt;/code&gt; (igual)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SimpleBeanPropertyFilter&lt;/code&gt; e &lt;code&gt;SimpleFilterProvider&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;...&lt;wbr/&gt;databind.&lt;wbr/&gt;ser.&lt;wbr/&gt;std&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;...&lt;wbr/&gt;databind.&lt;wbr/&gt;ser.&lt;wbr/&gt;impl&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;MapProperty&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;...&lt;wbr/&gt;databind.&lt;wbr/&gt;ser.&lt;wbr/&gt;jdk&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;...&lt;wbr/&gt;databind.&lt;wbr/&gt;ser.&lt;wbr/&gt;std&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Método do filtro&lt;/td&gt;&lt;td&gt;&lt;code&gt;serializeAsProperty(Object, JsonGenerator, SerializationContext, PropertyWriter)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;serializeAsField(Object, JsonGenerator, SerializerProvider, PropertyWriter)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Omitir campo&lt;/td&gt;&lt;td&gt;&lt;code&gt;writer.&lt;wbr/&gt;serializeAsOmittedProperty(...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;writer.&lt;wbr/&gt;serializeAsOmittedField(...)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Delegar ao fluxo normal&lt;/td&gt;&lt;td&gt;&lt;code&gt;writer.&lt;wbr/&gt;serializeAsProperty(...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;writer.&lt;wbr/&gt;serializeAsField(...)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Escrever o campo mascarado&lt;/td&gt;&lt;td&gt;&lt;code&gt;g.&lt;wbr/&gt;writeStringProperty(nome, valor)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;gen.&lt;wbr/&gt;writeStringField(nome, valor)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Registrar o provider&lt;/td&gt;&lt;td&gt;&lt;code&gt;JsonMapper.&lt;wbr/&gt;builder().&lt;wbr/&gt;filterProvider(...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;builder().&lt;wbr/&gt;filterProvider(...)&lt;/code&gt; ou &lt;code&gt;mapper.&lt;wbr/&gt;setFilterProvider(...)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Datas como ISO&lt;/td&gt;&lt;td&gt;&lt;code&gt;DateTimeFeature.&lt;wbr/&gt;WRITE_DATES_AS_TIMESTAMPS&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SerializationFeature.&lt;wbr/&gt;WRITE_DATES_AS_TIMESTAMPS&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Exceção de &lt;code&gt;writeValueAsString&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;JacksonException&lt;/code&gt; (unchecked)&lt;/td&gt;&lt;td&gt;&lt;code&gt;JsonProcessingException&lt;/code&gt; (checked)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;addMixIn&lt;/code&gt;, &lt;code&gt;BeanPropertyWriter&lt;/code&gt;, &lt;code&gt;PropertyWriter&lt;/code&gt; e o resto do fluxo funcionam da mesma forma.&lt;/p&gt;
&lt;h2 id=&quot;resumo&quot;&gt;Resumo&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;@JsonFilter&lt;/code&gt; dá um nome de filtro a uma classe, o &lt;code&gt;FilterProvider&lt;/code&gt; diz qual regra responde por esse nome, e o &lt;code&gt;PropertyFilter&lt;/code&gt; decide campo a campo o que escrever. Para mascarar, o filtro lê o valor e escreve a versão mascarada no lugar. Com um mixin em &lt;code&gt;Object.&lt;wbr/&gt;class&lt;/code&gt;, o filtro vale para todas as classes, mas só no mapper de log, e o mapper &lt;code&gt;@Primary&lt;/code&gt; continua servindo a API com os dados completos.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Jackson — &lt;a href=&quot;https://github.com/FasterXML/jackson/blob/main/jackson3/MIGRATING_TO_JACKSON_3.md&quot;&gt;Migrating to Jackson 3&lt;/a&gt; (pacote &lt;code&gt;tools.&lt;wbr/&gt;jackson&lt;/code&gt;, &lt;code&gt;SerializationContext&lt;/code&gt;, métodos “field” que viraram “property”, &lt;code&gt;JacksonException&lt;/code&gt; e &lt;code&gt;DateTimeFeature&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Jackson API — &lt;a href=&quot;https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-annotations/latest/com/fasterxml/jackson/annotation/JsonFilter.html&quot;&gt;&lt;code&gt;@JsonFilter&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://javadoc.io/doc/tools.jackson.core/jackson-databind/3.2.3/tools/jackson/databind/ser/PropertyFilter.html&quot;&gt;&lt;code&gt;PropertyFilter&lt;/code&gt;&lt;/a&gt; e &lt;a href=&quot;https://javadoc.io/doc/tools.jackson.core/jackson-databind/3.2.3/tools/jackson/databind/ser/std/SimpleBeanPropertyFilter.html&quot;&gt;&lt;code&gt;SimpleBeanPropertyFilter&lt;/code&gt;&lt;/a&gt; (Jackson 3.2.3)&lt;/li&gt;
&lt;li&gt;Jackson Wiki — &lt;a href=&quot;https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations&quot;&gt;Mix-in Annotations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Boot Reference — &lt;a href=&quot;https://docs.spring.io/spring-boot/how-to/spring-mvc.html#howto.spring-mvc.customize-jackson-jsonmapper&quot;&gt;Customize the Jackson JsonMapper&lt;/a&gt; (o &lt;code&gt;JsonMapper&lt;/code&gt; próprio com &lt;code&gt;@Primary&lt;/code&gt;, o &lt;code&gt;JsonMapper.&lt;wbr/&gt;Builder&lt;/code&gt; e as propriedades &lt;code&gt;spring.&lt;wbr/&gt;jackson.*&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;PCI SSC — &lt;a href=&quot;https://www.pcisecuritystandards.org/faq/articles/Frequently_Asked_Question/how-can-an-entity-meet-pci-dss-requirements-for-pan-masking-and-truncation-if-it-has-migrated-to-8-digit-bins/&quot;&gt;FAQ 1492: mascaramento e truncamento do PAN com BIN de 8 dígitos&lt;/a&gt; (requisito 3.4.1: no máximo o BIN e os 4 últimos dígitos)&lt;/li&gt;
&lt;li&gt;PCI SSC — &lt;a href=&quot;https://blog.pcisecuritystandards.org/faq-can-cvc-be-stored-for-card-on-file-or-recurring-transactions&quot;&gt;FAQ: o código de verificação pode ser guardado para cartão salvo ou cobrança recorrente?&lt;/a&gt; (não pode ser guardado depois da autorização, nem cifrado)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Desenvolvimento de Software</category><category>Spring</category><category>Logs</category><category>Pagamentos</category></item><item><title>CronJob ou endpoint + fila — onde rodar o batch de uma API Spring Boot no Kubernetes</title><link>https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/</guid><description>Uma API Spring Boot no Kubernetes precisa de uma rotina agendada: CronJob com a mesma imagem e o perfil batch, ou endpoint que enfileira no SQS para a própria API consumir? Onze critérios comparados.</description><pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Um cenário comum: um microsserviço Spring Boot roda no &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Kubernetes&lt;/span&gt; como API e passa a precisar de uma rotina periódica, por exemplo ler uma lista de registros do banco, aplicar validações e publicar parte deles num tópico SNS. A lógica de negócio já está no serviço, então a pergunta não é &lt;em&gt;se&lt;/em&gt; o código será reaproveitado, e sim &lt;mark class=&quot;caneta-marca&quot;&gt;&lt;em&gt;onde&lt;/em&gt; essa rotina vai rodar&lt;/mark&gt;.&lt;/p&gt;
&lt;p&gt;Duas abordagens aparecem com frequência. Ambas funcionam e reaproveitam o código, mas com trade-offs diferentes. Neste post, comparo as duas critério por critério, incluindo onde cada uma leva vantagem, e explico por que, para esse tipo de carga, a balança pende para a primeira.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Versões.&lt;/strong&gt; Os exemplos de código foram testados com Spring Boot 4.1.1 (que traz o Spring Batch 6.0.5), Java 21 e PostgreSQL 16, e o CronJob foi validado contra o schema da API do Kubernetes 1.37. Onde o Spring Boot 4 mudou o comportamento em relação ao 3.x, o texto avisa.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;as-duas-abordagens&quot;&gt;As duas abordagens&lt;/h2&gt;
&lt;h3 id=&quot;a--cronjob-com-a-mesma-imagem-e-outro-perfil-do-spring&quot;&gt;A — CronJob com a mesma imagem e outro perfil do Spring&lt;/h3&gt;
&lt;p&gt;A API continua no Deployment de sempre. No horário agendado, o CronJob cria um Job, que sobe um pod com &lt;strong&gt;a mesma imagem da API&lt;/strong&gt; e o perfil &lt;code&gt;batch&lt;/code&gt;: sem servidor web, esse pod executa o job com &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://spring.io/projects/spring-batch&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Spring Batch&lt;/span&gt; e termina. O exit code informa ao Kubernetes se deu certo.&lt;/p&gt;
&lt;p&gt;No diagrama, cada cor é um papel: o Kubernetes em azul, o pod do job em verde, a API em âmbar e o destino, o SNS, em petróleo. Os números seguem a ordem da execução, e os pontos que correm pelas setas também. Com o mouse numa cor da legenda, a figura destaca só aquele papel.&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 700&quot;
  aria-label=&quot;Abordagem A: às 03:00, o CronJob cria um Job, que sobe um pod com a mesma imagem da API e o perfil batch; o pod lê os pendentes no banco, publica no tópico SNS, marca os registros como enviados e termina, devolvendo o exit code ao Job, que tenta de novo até o backoffLimit; a API, no seu Deployment, só divide o banco com o job.&quot;&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;tom-azul&quot;&gt;
      &lt;rect x=&quot;37&quot; y=&quot;97&quot; width=&quot;210&quot; height=&quot;130&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;90&quot; width=&quot;210&quot; height=&quot;130&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;90&quot; width=&quot;210&quot; height=&quot;130&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M240 140 H296 M282 131 L296 140 L282 149&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;rect x=&quot;307&quot; y=&quot;97&quot; width=&quot;120&quot; height=&quot;130&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;300&quot; y=&quot;90&quot; width=&quot;120&quot; height=&quot;130&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;300&quot; y=&quot;90&quot; width=&quot;120&quot; height=&quot;130&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M420 120 H556 M542 111 L556 120 L542 129&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-verde&quot;&gt;
      &lt;rect x=&quot;570&quot; y=&quot;60&quot; width=&quot;320&quot; height=&quot;230&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;570&quot; y=&quot;60&quot; width=&quot;320&quot; height=&quot;230&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;570&quot; y=&quot;60&quot; width=&quot;320&quot; height=&quot;230&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;590&quot; y=&quot;128&quot; width=&quot;280&quot; height=&quot;44&quot; rx=&quot;6&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;590&quot; y=&quot;128&quot; width=&quot;280&quot; height=&quot;44&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M570 196 H434 M448 187 L434 196 L448 205&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M890 160 H971 M957 151 L971 160 L957 169&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M680 290 V372 M671 358 L680 372 L689 358&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M800 290 V372 M791 358 L800 372 L809 358&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-petroleo&quot;&gt;
      &lt;rect x=&quot;985&quot; y=&quot;95&quot; width=&quot;195&quot; height=&quot;135&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;985&quot; y=&quot;95&quot; width=&quot;195&quot; height=&quot;135&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;985&quot; y=&quot;95&quot; width=&quot;195&quot; height=&quot;135&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-ambar&quot;&gt;
      &lt;rect x=&quot;37&quot; y=&quot;377&quot; width=&quot;400&quot; height=&quot;200&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;370&quot; width=&quot;400&quot; height=&quot;200&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;370&quot; width=&quot;400&quot; height=&quot;200&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;90&quot; y=&quot;428&quot; width=&quot;280&quot; height=&quot;44&quot; rx=&quot;6&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;90&quot; y=&quot;428&quot; width=&quot;280&quot; height=&quot;44&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;path d=&quot;M652 404 V504 A93 20 0 0 0 838 504 V404&quot; transform=&quot;translate(10 10)&quot; class=&quot;hachura&quot;/&gt;
    &lt;path d=&quot;M652 404 V504 A93 20 0 0 0 838 504 V404 Z&quot; class=&quot;papel&quot;/&gt;
    &lt;path d=&quot;M652 404 V504 A93 20 0 0 0 838 504 V404&quot; class=&quot;linha&quot;/&gt;
    &lt;ellipse cx=&quot;745&quot; cy=&quot;404&quot; rx=&quot;93&quot; ry=&quot;20&quot; class=&quot;papel&quot;/&gt;
    &lt;ellipse cx=&quot;745&quot; cy=&quot;404&quot; rx=&quot;93&quot; ry=&quot;20&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M430 468 H650&quot; class=&quot;fantasma&quot;/&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;path d=&quot;M242 140 H290&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
    &lt;path d=&quot;M422 120 H550&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-2&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;path d=&quot;M680 292 V366&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-3&quot;/&gt;
    &lt;path d=&quot;M892 160 H965&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-4&quot;/&gt;
    &lt;path d=&quot;M800 292 V366&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-5&quot;/&gt;
    &lt;path d=&quot;M568 196 H440&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-6&quot;/&gt;
  &lt;/g&gt;

  &lt;g transform=&quot;translate(44 104) scale(0.48)&quot; class=&quot;marca marca-kubernetes tom-azul&quot;&gt;&lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M71 51.6 A21 21 0 1 1 29 51.6 A21 21 0 1 1 71 51.6 Z M65 51.6 A15 15 0 1 0 35 51.6 A15 15 0 1 0 65 51.6 Z&quot; fill-rule=&quot;evenodd&quot;/&gt;
    &lt;circle cx=&quot;50&quot; cy=&quot;51.6&quot; r=&quot;5.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(51.43 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(102.86 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(154.29 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(205.71 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(257.14 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(308.57 50 51.6)&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(584 74) scale(0.44)&quot; class=&quot;marca marca-spring tom-verde&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(1057 106) scale(0.5)&quot; class=&quot;marca marca-sns tom-petroleo&quot;&gt;&lt;g class=&quot;tinta tom-roxo&quot;&gt;
    &lt;circle cx=&quot;48&quot; cy=&quot;50&quot; r=&quot;36&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M70.2 21.6 A36 36 0 1 0 70.2 78.4&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M28 38 H54 L45 53 V64 L37 60 V53 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M17 50 H33 M48 50 H64 M64 28 V72 M64 28 H76 M64 72 H76 M64 50 H80&quot; class=&quot;linha&quot;/&gt;
    &lt;circle cx=&quot;12&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;82&quot; cy=&quot;28&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;86&quot; cy=&quot;50&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;82&quot; cy=&quot;72&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(46 384) scale(0.44)&quot; class=&quot;marca marca-spring tom-ambar&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;text x=&quot;102&quot; y=&quot;146&quot; class=&quot;titulo-caixa&quot;&gt;CronJob&lt;/text&gt;
    &lt;text x=&quot;102&quot; y=&quot;194&quot; class=&quot;codigo&quot;&gt;03:00&lt;/text&gt;
    &lt;text x=&quot;360&quot; y=&quot;164&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Job&lt;/text&gt;
    &lt;circle cx=&quot;268&quot; cy=&quot;110&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;268&quot; y=&quot;111&quot; class=&quot;selo-texto&quot;&gt;1&lt;/text&gt;
    &lt;text x=&quot;268&quot; y=&quot;176&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;cria&lt;/text&gt;
    &lt;circle cx=&quot;488&quot; cy=&quot;90&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;488&quot; y=&quot;91&quot; class=&quot;selo-texto&quot;&gt;2&lt;/text&gt;
    &lt;text x=&quot;488&quot; y=&quot;158&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;sobe o pod&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;text x=&quot;640&quot; y=&quot;108&quot; class=&quot;titulo-caixa&quot;&gt;Pod do job&lt;/text&gt;
    &lt;text x=&quot;730&quot; y=&quot;159&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;meu-servico:1.2.3&lt;/text&gt;
    &lt;text x=&quot;730&quot; y=&quot;208&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;perfil batch, sem web&lt;/text&gt;
    &lt;text x=&quot;730&quot; y=&quot;243&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom texto-caixa&quot;&gt;roda o lote e termina&lt;/text&gt;
    &lt;text x=&quot;730&quot; y=&quot;273&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;recurso só durante a execução&lt;/text&gt;
    &lt;circle cx=&quot;452&quot; cy=&quot;237&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;452&quot; y=&quot;238&quot; class=&quot;selo-texto&quot;&gt;6&lt;/text&gt;
    &lt;text x=&quot;474&quot; y=&quot;244&quot; class=&quot;nota-pequena&quot;&gt;exit code&lt;/text&gt;
    &lt;circle cx=&quot;937&quot; cy=&quot;128&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;937&quot; y=&quot;129&quot; class=&quot;selo-texto&quot;&gt;4&lt;/text&gt;
    &lt;text x=&quot;937&quot; y=&quot;196&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;publica&lt;/text&gt;
    &lt;circle cx=&quot;650&quot; cy=&quot;331&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;650&quot; y=&quot;332&quot; class=&quot;selo-texto&quot;&gt;3&lt;/text&gt;
    &lt;text x=&quot;628&quot; y=&quot;338&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;lê os pendentes&lt;/text&gt;
    &lt;circle cx=&quot;830&quot; cy=&quot;331&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;830&quot; y=&quot;332&quot; class=&quot;selo-texto&quot;&gt;5&lt;/text&gt;
    &lt;text x=&quot;854&quot; y=&quot;338&quot; class=&quot;nota-pequena&quot;&gt;marca como enviado&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;
    &lt;text x=&quot;1082&quot; y=&quot;206&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Tópico SNS&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;text x=&quot;100&quot; y=&quot;412&quot; class=&quot;titulo-caixa&quot;&gt;Deployment da API&lt;/text&gt;
    &lt;text x=&quot;230&quot; y=&quot;459&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;meu-servico:1.2.3&lt;/text&gt;
    &lt;text x=&quot;230&quot; y=&quot;512&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;perfil padrão, com servidor web&lt;/text&gt;
    &lt;text x=&quot;230&quot; y=&quot;545&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;atende HTTP o dia todo&lt;/text&gt;
  &lt;/g&gt;
  &lt;text x=&quot;360&quot; y=&quot;292&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;se ≠ 0, o Job tenta de novo,&lt;/text&gt;
  &lt;text x=&quot;360&quot; y=&quot;316&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;até o backoffLimit&lt;/text&gt;
  &lt;text x=&quot;745&quot; y=&quot;470&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Banco&lt;/text&gt;
  &lt;text x=&quot;540&quot; y=&quot;454&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;mesmo banco&lt;/text&gt;
  &lt;text x=&quot;600&quot; y=&quot;620&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;Um deploy da API não interrompe o job em andamento: a próxima execução usa a imagem que estiver no CronJob.&lt;/text&gt;

  &lt;g class=&quot;legenda tom-azul&quot;&gt;&lt;rect x=&quot;200&quot; y=&quot;660&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;232&quot; y=&quot;674&quot; class=&quot;nota-pequena&quot;&gt;Kubernetes&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-verde&quot;&gt;&lt;rect x=&quot;380&quot; y=&quot;660&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;412&quot; y=&quot;674&quot; class=&quot;nota-pequena&quot;&gt;pod do job (A)&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-ambar&quot;&gt;&lt;rect x=&quot;590&quot; y=&quot;660&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;622&quot; y=&quot;674&quot; class=&quot;nota-pequena&quot;&gt;API&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-petroleo&quot;&gt;&lt;rect x=&quot;700&quot; y=&quot;660&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;732&quot; y=&quot;674&quot; class=&quot;nota-pequena&quot;&gt;destino (SNS)&lt;/text&gt;&lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;A mesma imagem em dois processos: a API atende HTTP o dia todo, e o pod do job só existe enquanto o lote roda.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;b--cronjob-chama-um-endpoint-que-enfileira-uma-mensagem-no-sqs-e-a-própria-api-a-consome&quot;&gt;B — CronJob chama um endpoint que enfileira uma mensagem no SQS, e a própria API a consome&lt;/h3&gt;
&lt;p&gt;No horário agendado, o CronJob chama um endpoint da API com &lt;code&gt;curl&lt;/code&gt;. O endpoint publica uma única mensagem numa fila &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://aws.amazon.com/sqs/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;SQS&lt;/span&gt;, um pedido para processar os pendentes, e responde &lt;code&gt;202 Accepted&lt;/code&gt;, sem consultar o banco. Um dos pods da API consome essa mensagem (por exemplo, com o &lt;code&gt;@SqsListener&lt;/code&gt; do Spring Cloud AWS): lê os registros pendentes no banco e processa um a um, publicando no SNS e marcando o status de cada registro. Se der erro, a mensagem não é apagada e volta a ficar visível na fila (ela nunca sai de lá; só fica invisível enquanto é processada), e a nova tentativa segue de onde a anterior parou, porque &lt;mark class=&quot;caneta-grifo&quot;&gt;o banco diz o que já foi enviado&lt;/mark&gt;. Depois de N tentativas, a mensagem vai para a DLQ (&lt;em&gt;dead-letter queue&lt;/em&gt;, a fila das mensagens que falharam).&lt;/p&gt;
&lt;p&gt;O diagrama usa as mesmas cores, com a fila e a DLQ em roxo, a cor da abordagem B, e o caminho de erro em vermelho. O lote inteiro passa pelo listener, dentro dos mesmos pods que atendem as requisições.&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 790&quot;
  aria-label=&quot;Abordagem B: o CronJob chama POST /processar; o endpoint da API publica uma única mensagem no SQS e responde 202; um listener nos mesmos pods consome a mensagem, lê os pendentes no banco, publica cada registro no SNS e marca o status; se der erro, a mensagem reaparece depois do visibility timeout e, após N recebimentos, vai para a DLQ, de onde volta por redrive.&quot;&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;tom-azul&quot;&gt;
      &lt;rect x=&quot;32&quot; y=&quot;102&quot; width=&quot;210&quot; height=&quot;120&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;95&quot; width=&quot;210&quot; height=&quot;120&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;95&quot; width=&quot;210&quot; height=&quot;120&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M235 150 H496 M482 141 L496 150 L482 159&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-ambar&quot;&gt;
      &lt;rect x=&quot;482&quot; y=&quot;47&quot; width=&quot;330&quot; height=&quot;430&quot; rx=&quot;14&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;475&quot; y=&quot;40&quot; width=&quot;330&quot; height=&quot;430&quot; rx=&quot;14&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;475&quot; y=&quot;40&quot; width=&quot;330&quot; height=&quot;430&quot; rx=&quot;14&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;500&quot; y=&quot;100&quot; width=&quot;280&quot; height=&quot;110&quot; rx=&quot;10&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;500&quot; y=&quot;100&quot; width=&quot;280&quot; height=&quot;110&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;500&quot; y=&quot;300&quot; width=&quot;280&quot; height=&quot;120&quot; rx=&quot;10&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;500&quot; y=&quot;300&quot; width=&quot;280&quot; height=&quot;120&quot; rx=&quot;10&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M780 140 H1020 C 1050 140 1060 160 1060 204 M1051 202 L1060 216 L1069 202&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M500 395 H255 C 185 395 150 420 150 494 M141 482 L150 496 L159 482&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M640 420 V528 M631 516 L640 530 L649 516&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;
      &lt;rect x=&quot;935&quot; y=&quot;220&quot; width=&quot;245&quot; height=&quot;120&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;935&quot; y=&quot;220&quot; width=&quot;245&quot; height=&quot;120&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;935&quot; y=&quot;220&quot; width=&quot;245&quot; height=&quot;120&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M935 290 C 880 290 850 350 796 350 M809 341 L795 350 L809 359&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M1080 340 V564 M1071 552 L1080 566 L1089 552&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M1160 580 V356&quot; class=&quot;fantasma&quot;/&gt;
      &lt;path d=&quot;M1151 356 L1160 342 L1169 356&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;rect x=&quot;942&quot; y=&quot;587&quot; width=&quot;238&quot; height=&quot;100&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;935&quot; y=&quot;580&quot; width=&quot;238&quot; height=&quot;100&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;935&quot; y=&quot;580&quot; width=&quot;238&quot; height=&quot;100&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;
      &lt;path d=&quot;M780 402 H975 V356&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M966 356 L975 342 L984 356&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-petroleo&quot;&gt;
      &lt;rect x=&quot;515&quot; y=&quot;545&quot; width=&quot;250&quot; height=&quot;110&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;515&quot; y=&quot;545&quot; width=&quot;250&quot; height=&quot;110&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;515&quot; y=&quot;545&quot; width=&quot;250&quot; height=&quot;110&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;path d=&quot;M35 520 V612 A95 18 0 0 0 225 612 V520&quot; transform=&quot;translate(10 10)&quot; class=&quot;hachura&quot;/&gt;
    &lt;path d=&quot;M35 520 V612 A95 18 0 0 0 225 612 V520 Z&quot; class=&quot;papel&quot;/&gt;
    &lt;path d=&quot;M35 520 V612 A95 18 0 0 0 225 612 V520&quot; class=&quot;linha&quot;/&gt;
    &lt;ellipse cx=&quot;130&quot; cy=&quot;520&quot; rx=&quot;95&quot; ry=&quot;18&quot; class=&quot;papel&quot;/&gt;
    &lt;ellipse cx=&quot;130&quot; cy=&quot;520&quot; rx=&quot;95&quot; ry=&quot;18&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;path d=&quot;M237 150 H490&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;path d=&quot;M782 140 H1020 C 1050 140 1060 160 1060 210&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-2&quot;/&gt;
    &lt;path d=&quot;M498 395 H255 C 185 395 150 420 150 490&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-4&quot;/&gt;
    &lt;path d=&quot;M640 422 V524&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-5&quot;/&gt;
    &lt;path d=&quot;M498 395 H255 C 185 395 150 420 150 490&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-6&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;path d=&quot;M933 290 C 880 290 850 350 801 350&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-3&quot;/&gt;
  &lt;/g&gt;

  &lt;g transform=&quot;translate(37 108) scale(0.46)&quot; class=&quot;marca marca-kubernetes tom-azul&quot;&gt;&lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M71 51.6 A21 21 0 1 1 29 51.6 A21 21 0 1 1 71 51.6 Z M65 51.6 A15 15 0 1 0 35 51.6 A15 15 0 1 0 65 51.6 Z&quot; fill-rule=&quot;evenodd&quot;/&gt;
    &lt;circle cx=&quot;50&quot; cy=&quot;51.6&quot; r=&quot;5.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(51.43 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(102.86 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(154.29 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(205.71 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(257.14 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(308.57 50 51.6)&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(489 52) scale(0.4)&quot; class=&quot;marca marca-spring tom-ambar&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(947 232) scale(0.46)&quot; class=&quot;marca marca-sqs tom-roxo&quot;&gt;&lt;g class=&quot;tinta tom-roxo&quot;&gt;
    &lt;path d=&quot;M38 36 Q50 43 62 36 Q55 50 62 64 Q50 57 38 64 Q45 50 38 36 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M38 36 Q50 43 62 36 Q55 50 62 64 Q50 57 38 64 Q45 50 38 36 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M15.6 33.9 A38 38 0 0 1 84.4 33.9 M15.6 66.1 A38 38 0 0 0 84.4 66.1&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M22 50 H33 M29 45 L34 50 L29 55 M66 50 H77 M73 45 L78 50 L73 55&quot; class=&quot;linha&quot;/&gt;
    &lt;circle cx=&quot;12&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;88&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(527 558) scale(0.44)&quot; class=&quot;marca marca-sns tom-petroleo&quot;&gt;&lt;g class=&quot;tinta tom-roxo&quot;&gt;
    &lt;circle cx=&quot;48&quot; cy=&quot;50&quot; r=&quot;36&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M70.2 21.6 A36 36 0 1 0 70.2 78.4&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M28 38 H54 L45 53 V64 L37 60 V53 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M17 50 H33 M48 50 H64 M64 28 V72 M64 28 H76 M64 72 H76 M64 50 H80&quot; class=&quot;linha&quot;/&gt;
    &lt;circle cx=&quot;12&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;82&quot; cy=&quot;28&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;86&quot; cy=&quot;50&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;82&quot; cy=&quot;72&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;text x=&quot;92&quot; y=&quot;150&quot; class=&quot;titulo-caixa&quot;&gt;CronJob&lt;/text&gt;
    &lt;text x=&quot;92&quot; y=&quot;192&quot; class=&quot;codigo&quot;&gt;03:00&lt;/text&gt;
    &lt;circle cx=&quot;268&quot; cy=&quot;118&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;268&quot; y=&quot;119&quot; class=&quot;selo-texto&quot;&gt;1&lt;/text&gt;
    &lt;text x=&quot;292&quot; y=&quot;125&quot; class=&quot;nota-pequena&quot;&gt;curl&lt;/text&gt;
    &lt;text x=&quot;356&quot; y=&quot;192&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;POST /processar&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;text x=&quot;539&quot; y=&quot;84&quot; class=&quot;titulo-caixa&quot;&gt;Pods da API&lt;/text&gt;
    &lt;text x=&quot;640&quot; y=&quot;147&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Endpoint&lt;/text&gt;
    &lt;text x=&quot;640&quot; y=&quot;184&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;responde 202 Accepted&lt;/text&gt;
    &lt;text x=&quot;640&quot; y=&quot;350&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Listener SQS&lt;/text&gt;
    &lt;text x=&quot;640&quot; y=&quot;388&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;processa um a um&lt;/text&gt;
    &lt;circle cx=&quot;836&quot; cy=&quot;113&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;836&quot; y=&quot;114&quot; class=&quot;selo-texto&quot;&gt;2&lt;/text&gt;
    &lt;text x=&quot;860&quot; y=&quot;120&quot; class=&quot;nota-pequena&quot;&gt;publica 1 mensagem&lt;/text&gt;
    &lt;circle cx=&quot;235&quot; cy=&quot;355&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;235&quot; y=&quot;356&quot; class=&quot;selo-texto&quot;&gt;4&lt;/text&gt;
    &lt;text x=&quot;259&quot; y=&quot;362&quot; class=&quot;nota-pequena&quot;&gt;lê os pendentes&lt;/text&gt;
    &lt;circle cx=&quot;235&quot; cy=&quot;438&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;235&quot; y=&quot;439&quot; class=&quot;selo-texto&quot;&gt;6&lt;/text&gt;
    &lt;text x=&quot;259&quot; y=&quot;445&quot; class=&quot;nota-pequena&quot;&gt;marca como enviado&lt;/text&gt;
    &lt;circle cx=&quot;667&quot; cy=&quot;500&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;667&quot; y=&quot;501&quot; class=&quot;selo-texto&quot;&gt;5&lt;/text&gt;
    &lt;text x=&quot;691&quot; y=&quot;507&quot; class=&quot;nota-pequena&quot;&gt;publica&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;text x=&quot;1005&quot; y=&quot;264&quot; class=&quot;titulo-caixa&quot;&gt;Fila SQS&lt;/text&gt;
    &lt;text x=&quot;1057&quot; y=&quot;302&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;1 mensagem&lt;/text&gt;
    &lt;text x=&quot;1057&quot; y=&quot;328&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;por execução&lt;/text&gt;
    &lt;circle cx=&quot;835&quot; cy=&quot;262&quot; r=&quot;16&quot; class=&quot;selo&quot;/&gt;
    &lt;text x=&quot;835&quot; y=&quot;263&quot; class=&quot;selo-texto&quot;&gt;3&lt;/text&gt;
    &lt;text x=&quot;857&quot; y=&quot;269&quot; class=&quot;nota-pequena&quot;&gt;entrega&lt;/text&gt;
    &lt;text x=&quot;1070&quot; y=&quot;530&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;após N&lt;/text&gt;
    &lt;text x=&quot;1070&quot; y=&quot;554&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;recebimentos&lt;/text&gt;
    &lt;text x=&quot;1152&quot; y=&quot;470&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;redrive&lt;/text&gt;
    &lt;text x=&quot;1054&quot; y=&quot;623&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;DLQ&lt;/text&gt;
    &lt;text x=&quot;1054&quot; y=&quot;658&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;a mensagem do lote&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-vermelho&quot;&gt;
    &lt;text x=&quot;815&quot; y=&quot;436&quot; class=&quot;texto-tom nota-pequena&quot;&gt;erro: a mensagem volta&lt;/text&gt;
    &lt;text x=&quot;815&quot; y=&quot;460&quot; class=&quot;texto-tom nota-pequena&quot;&gt;após o visibility timeout&lt;/text&gt;
    &lt;text x=&quot;815&quot; y=&quot;484&quot; class=&quot;texto-tom nota-pequena&quot;&gt;e retoma de onde parou&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-petroleo&quot;&gt;
    &lt;text x=&quot;583&quot; y=&quot;598&quot; class=&quot;titulo-caixa&quot;&gt;Tópico SNS&lt;/text&gt;
    &lt;text x=&quot;640&quot; y=&quot;636&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;destino dos registros&lt;/text&gt;
  &lt;/g&gt;
  &lt;text x=&quot;130&quot; y=&quot;585&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;Banco&lt;/text&gt;
  &lt;text x=&quot;600&quot; y=&quot;722&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;O lote divide o processo com as requisições: pool de conexões, CPU e heap.&lt;/text&gt;

  &lt;g class=&quot;legenda tom-azul&quot;&gt;&lt;rect x=&quot;160&quot; y=&quot;752&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;192&quot; y=&quot;766&quot; class=&quot;nota-pequena&quot;&gt;Kubernetes&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-ambar&quot;&gt;&lt;rect x=&quot;330&quot; y=&quot;752&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;362&quot; y=&quot;766&quot; class=&quot;nota-pequena&quot;&gt;API&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-roxo&quot;&gt;&lt;rect x=&quot;440&quot; y=&quot;752&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;472&quot; y=&quot;766&quot; class=&quot;nota-pequena&quot;&gt;fila SQS (B)&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-petroleo&quot;&gt;&lt;rect x=&quot;610&quot; y=&quot;752&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;642&quot; y=&quot;766&quot; class=&quot;nota-pequena&quot;&gt;destino (SNS)&lt;/text&gt;&lt;/g&gt;
  &lt;g class=&quot;legenda tom-vermelho&quot;&gt;&lt;rect x=&quot;800&quot; y=&quot;752&quot; width=&quot;22&quot; height=&quot;16&quot; rx=&quot;3&quot; class=&quot;lavado&quot;/&gt;&lt;text x=&quot;832&quot; y=&quot;766&quot; class=&quot;nota-pequena&quot;&gt;caminho de erro&lt;/text&gt;&lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;Uma mensagem por execução: o lote inteiro roda no listener, dentro dos pods da API, e o erro devolve a mensagem à fila.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;A abordagem B &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;não é um antipadrão&lt;/span&gt;. Entre os exemplos de gatilho agendado para processamento em segundo plano, a Microsoft cita exatamente esse desenho: um timer em outra aplicação envia periodicamente uma requisição a uma API, e a API dispara a tarefa (&lt;a href=&quot;https://learn.microsoft.com/azure/architecture/best-practices/background-jobs&quot;&gt;Microsoft — Best practices for background jobs&lt;/a&gt;). A discussão aqui é de trade-off.&lt;/p&gt;
&lt;h2 id=&quot;o-padrão-por-trás-da-abordagem-a&quot;&gt;O padrão por trás da abordagem A&lt;/h2&gt;
&lt;div class=&quot;caneta-moldura&quot;&gt;&lt;p&gt;Rodar a mesma base de código como tipos diferentes de processo é um princípio do &lt;a href=&quot;https://12factor.net/concurrency&quot;&gt;Twelve-Factor App&lt;/a&gt; (fator VIII, &lt;em&gt;Concurrency&lt;/em&gt;): o processo web atende HTTP, e o worker executa tarefas longas em segundo plano.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Chris Jones, da AWS Professional Services, descreve uma evolução em três passos em &lt;a href=&quot;https://thenewstack.io/rethinking-java-scheduled-tasks-in-kubernetes/&quot;&gt;Rethinking Java @Scheduled Tasks in Kubernetes&lt;/a&gt; (The New Stack, 2023): primeiro o &lt;code&gt;@Scheduled&lt;/code&gt; dentro da API, depois um CronJob que chama um endpoint via &lt;code&gt;curl&lt;/code&gt; e, por fim, um CronJob que roda a mesma imagem da API com um ponto de entrada alternativo. Ele detalha o padrão no AWS Open Source Blog, em &lt;a href=&quot;https://aws.amazon.com/blogs/opensource/alternative-jar-entry-points-using-a-dependency-injection-framework-for-existing-java-applications/&quot;&gt;Alternative JAR Entry Points Using Java Dependency Injection Frameworks&lt;/a&gt;, com um &lt;a href=&quot;https://github.com/aws-samples/multiple-entry-points-with-dependency-injection&quot;&gt;código de exemplo&lt;/a&gt; em que o &lt;code&gt;main&lt;/code&gt; escolhe o ponto de entrada por uma variável de ambiente própria (&lt;code&gt;ALTERNATIVE_ENTRY_POINT&lt;/code&gt;). No Spring Boot, um caminho comum para o mesmo efeito é um perfil (&lt;a href=&quot;https://docs.spring.io/spring-boot/reference/features/profiles.html&quot;&gt;Spring Boot — Profiles&lt;/a&gt;): o perfil &lt;code&gt;batch&lt;/code&gt; troca beans e configuração e é ativado no CronJob pela variável &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;SPRING_PROFILES_ACTIVE&lt;/code&gt;&lt;/span&gt;, como mostra a seção &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/#como-montar-a-abordagem-a&quot;&gt;Como montar a abordagem A&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Uma alternativa frequente ao primeiro passo, &lt;code&gt;@Scheduled&lt;/code&gt; com &lt;a href=&quot;https://github.com/lukas-krecan/ShedLock&quot;&gt;ShedLock&lt;/a&gt;, &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;só impede&lt;/span&gt; que duas réplicas rodem a tarefa ao mesmo tempo. O processamento continua dentro da API, com os problemas dos critérios 1 a 4 e sem os ganhos da fila.&lt;/p&gt;
&lt;p&gt;Mahmoud Ben Hassine, líder do projeto Spring Batch, mostra como rodar jobs do Spring Batch como Jobs do Kubernetes em &lt;a href=&quot;https://spring.io/blog/2021/01/27/spring-batch-on-kubernetes-efficient-batch-processing-at-scale&quot;&gt;Spring Batch on Kubernetes: Efficient batch processing at scale&lt;/a&gt; (Spring blog, 2021). O texto é da época do Spring Batch 4; o que mudou desde então aparece ao longo deste post.&lt;/p&gt;
&lt;h2 id=&quot;critério-a-critério&quot;&gt;Critério a critério&lt;/h2&gt;
&lt;h3 id=&quot;1-disputa-de-recursos-com-quem-atende-o-usuário&quot;&gt;1. Disputa de recursos com quem atende o usuário&lt;/h3&gt;
&lt;p&gt;Na abordagem B, o lote roda dentro de um pod da API, o que recebeu a mensagem, e esse pod continua atendendo a sua parte das requisições. O batch e as requisições HTTP passam a &lt;span class=&quot;caneta caneta-duplo&quot;&gt;dividir o mesmo processo&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pool de conexões.&lt;/strong&gt; O &lt;a href=&quot;https://github.com/brettwooldridge/HikariCP&quot;&gt;HikariCP&lt;/a&gt;, pool que o Spring Boot usa por padrão, abre no máximo &lt;span class=&quot;caneta caneta-circulo&quot;&gt;10&lt;/span&gt; conexões, e o lote usa esse mesmo pool. Processando em série, ele ocupa uma conexão por vez; se o consumidor dividir o lote entre várias threads para terminar antes, ocupa várias, e as requisições da API esperam por uma conexão livre até estourar o timeout (30 s por padrão).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU.&lt;/strong&gt; O limite de CPU do container é um só: o que o batch consome, as requisições que caem nesse pod perdem em &lt;span class=&quot;caneta caneta-tendencia&quot;&gt;latência&lt;span class=&quot;caneta-tendencia-seta&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (aumenta)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heap.&lt;/strong&gt; O heap é a área de memória da JVM onde vivem os objetos. Processar grandes volumes aumenta o trabalho do garbage collector, e as pausas dele atingem a aplicação inteira. No limite, a JVM lança &lt;code&gt;OutOfMemoryError&lt;/code&gt;, ou o container passa do limite de memória e é morto pelo kernel (OOMKilled), levando junto as requisições em andamento.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;mark class=&quot;caneta-grifo&quot;&gt;Isolar recursos por tipo de carga&lt;/mark&gt;, para que uma não esgote a outra, é o padrão Bulkhead, popularizado por Michael Nygard em &lt;em&gt;Release It!&lt;/em&gt; e documentado pela Microsoft (&lt;a href=&quot;https://learn.microsoft.com/azure/architecture/patterns/bulkhead&quot;&gt;Bulkhead pattern&lt;/a&gt;). Martin Kleppmann ajuda a entender por que as duas cargas não combinam: em serviços online, a principal medida de desempenho é o tempo de resposta, e a disponibilidade costuma ser crítica; em sistemas batch, é o throughput (&lt;a href=&quot;https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/ch10.html&quot;&gt;&lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt;, 1ª ed., cap. 10&lt;/a&gt;). O Borg, gerenciador de clusters do Google e antecessor do Kubernetes, trata serviços de longa duração e jobs batch como classes distintas de carga, com prioridades diferentes (&lt;a href=&quot;https://research.google/pubs/large-scale-cluster-management-at-google-with-borg/&quot;&gt;Verma et al., EuroSys 2015&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Na abordagem A, o job roda num pod separado, com seus próprios requests e limites de CPU e memória e seu pool de conexões.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-asterisco&quot;&gt;&lt;p&gt;&lt;strong&gt;Ressalva:&lt;/strong&gt; o banco continua compartilhado. O pod separado isola o processo, não o banco. Por isso, o job deve ter um pool pequeno (mas não menor que o número de threads do step) e chunks, a quantidade de itens gravados por transação, bem dimensionados.&lt;/p&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-deploy-da-api-no-meio-do-processamento&quot;&gt;2. Deploy da API no meio do processamento&lt;/h3&gt;
&lt;p&gt;Na abordagem B, um deploy da API feito durante a janela do batch acontece no meio do processamento. No rolling update, cada pod antigo recebe SIGTERM e tem o grace period (30 segundos por padrão) para encerrar antes do SIGKILL (&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination&quot;&gt;Kubernetes — término de pods&lt;/a&gt;; o ciclo completo está em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/sigterm-sigkill-kubernetes/&quot;&gt;SIGTERM e SIGKILL&lt;/a&gt;). O graceful shutdown do Spring Boot cuida das requisições HTTP (&lt;a href=&quot;https://docs.spring.io/spring-boot/reference/web/graceful-shutdown.html&quot;&gt;Spring Boot — Graceful shutdown&lt;/a&gt;); o listener da fila &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;tem prazo próprio&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;20 s no Spring Cloud AWS&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Quando chega a vez do pod que está com a mensagem do lote:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;o listener para de buscar mensagens e espera a que está em andamento, no Spring Cloud AWS até 20 s por padrão (&lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;listenerShutdownTimeout&lt;/code&gt;&lt;/span&gt;). Um lote de minutos não termina nesse prazo, e o processamento é cancelado;&lt;/li&gt;
&lt;li&gt;como não foi concluída, a mensagem não foi apagada da fila: reaparece depois do visibility timeout (o prazo em que a mensagem recebida fica invisível para os outros consumidores), e um pod da versão nova a recebe e segue de onde o anterior parou, pelo status no banco. Se o registro que estava em andamento já tinha sido publicado no SNS, mas ainda não tinha sido marcado, &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;ele é enviado de novo&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;duplicado no SNS&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;;&lt;/li&gt;
&lt;li&gt;o lote termina &lt;span class=&quot;caneta caneta-duplo&quot;&gt;em duas versões do código&lt;/span&gt;: parte processada pela antiga, parte pela nova.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A lousa põe as duas abordagens no mesmo relógio: um lote que leva 1h10, um deploy da API às 03:30 e, na B, um visibility timeout de 2 horas. Em cima, na A, o deploy troca a API de versão, e o pod do job segue até o fim. Embaixo, na B, o deploy cancela o lote no meio, e a mensagem fica invisível na fila até as 05:00. O play mostra o tempo correndo, e arrastar sobre o desenho leva a qualquer instante.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lousa comparando um deploy da API às 03:30 nas duas abordagens: na A, a API passa da v1 para a v2, e o pod do job segue e termina às 04:10 na v1; na B, o pod v1 é cancelado no meio do lote, a mensagem fica invisível até as 05:00, e só então o pod v2 a recebe e retoma de onde a v1 parou, com o lote parado 1h30 e terminado em duas versões.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/&quot;&gt;A lousa interativa está no site.&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-colchete&quot;&gt;&lt;p&gt;Como a mensagem é uma só, o deploy não põe em risco só o registro em andamento: o lote inteiro para, e a retomada espera o visibility timeout expirar. Se ele foi dimensionado para cobrir o lote (critério 6), a espera pode ser longa: no exemplo, um deploy às 03:30 deixa o lote parado até as 05:00. Aumentar o grace period não resolve: ele é só um teto, não muda o prazo do listener e teria de cobrir o lote inteiro. O resultado costuma ser o time evitando deploy na janela do batch.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Na abordagem A, o deploy da API não toca no pod do job. Nem mesmo uma atualização do CronJob afeta o que já está rodando: as mudanças valem só para os Jobs criados depois, e os que já começaram seguem sem alteração (&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#modifying-a-cronjob&quot;&gt;Kubernetes — CronJob&lt;/a&gt;). &lt;mark class=&quot;caneta-grifo&quot;&gt;O job de hoje termina com a versão com que começou&lt;/mark&gt;, e a nova versão entra na próxima execução. Isso vale para o código, não para o banco: se a versão nova da API roda migrações, elas precisam ser compatíveis com o job que ainda está rodando (&lt;em&gt;expand/contract&lt;/em&gt;), a mesma disciplina que o próprio rolling update já exige.&lt;/p&gt;
&lt;h3 id=&quot;3-recurso-reservado-o-dia-inteiro&quot;&gt;3. Recurso reservado o dia inteiro&lt;/h3&gt;
&lt;p&gt;No Kubernetes, cada container declara quanto de memória e CPU reserva no cluster (os &lt;em&gt;requests&lt;/em&gt;). Desde a versão 1.35 (estável; em beta desde a 1.33), dá para redimensionar um pod em execução (&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-resize&quot;&gt;Kubernetes — Resizing Pods&lt;/a&gt;), mas nada no Kubernetes faz isso sozinho só nos minutos em que o batch roda. E, numa JVM, memória a mais sem reiniciar o container &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;não aumenta o heap&lt;/span&gt;, porque o tamanho máximo dele é fixado quando a JVM sobe. O &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/autoscaling/vertical-pod-autoscale/&quot;&gt;Vertical Pod Autoscaler&lt;/a&gt;, instalado à parte, também não resolve: para memória, ele considera o pico de cada período de 24 horas, então recomendaria reservar o pico do batch o dia inteiro.&lt;/p&gt;
&lt;p&gt;Na abordagem B, cada réplica da API precisa de folga para o pico do batch, 24 horas por dia: qualquer uma pode receber a mensagem e rodar o lote inteiro (critério 6). Essa folga precisa estar no request: memória não se comprime, e, quando falta memória no nó, os pods que passam do próprio request tendem a ser os primeiros despejados (&lt;a href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/&quot;&gt;Kubernetes — requests e limits&lt;/a&gt;). Um exemplo com números hipotéticos: a API precisa de 512 MB, e o lote, de mais 1 GB. Como qualquer réplica pode recebê-lo, cada uma reserva 1,5 GB, e, com três réplicas, são &lt;span class=&quot;caneta caneta-explica&quot;&gt;&lt;span class=&quot;caneta-explica-alvo&quot;&gt;4,5 GB&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-explica-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (quer dizer: &lt;/span&gt;3 réplicas × 1,5 GB&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; reservados o tempo todo. Na abordagem A, são 1,5 GB para a API e 1 GB para o pod do job, só enquanto ele roda: terminado o Job, o pod fica como &lt;code&gt;Completed&lt;/code&gt; e deixa de reservar CPU e memória. Ele pode continuar existindo como registro, para consulta de logs, até ser removido pelo limite de histórico do CronJob (&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/job/#job-termination-and-cleanup&quot;&gt;Kubernetes — Jobs&lt;/a&gt;). O paper do Borg registra o mesmo desperdício do lado dos serviços: jobs de produção costumam reservar recurso para picos raros e não usá-lo na maior parte do tempo.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-validade&quot;&gt;&lt;span class=&quot;caneta-sinal-margem caneta-validade-onda&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;p&gt;Sobre a fatura: o SQS custa pouco, e o nível gratuito inclui 1 milhão de requisições por mês, somadas todas as filas da conta (&lt;a href=&quot;https://aws.amazon.com/sqs/pricing/&quot;&gt;Amazon SQS — Pricing&lt;/a&gt;). O que pesa não é a conta do SQS, e sim o custo total de propriedade: recurso reservado e mais peças para provisionar, proteger e monitorar em cada ambiente.&lt;/p&gt;&lt;/div&gt;
&lt;p class=&quot;caneta-escrita caneta-validade-nota&quot;&gt;conferido em set/2026&lt;/p&gt;
&lt;h3 id=&quot;4-autoscaling-reagindo-ao-batch-e-não-aos-usuários&quot;&gt;4. Autoscaling reagindo ao batch, e não aos usuários&lt;/h3&gt;
&lt;p&gt;O &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/&quot;&gt;HPA (Horizontal Pod Autoscaler)&lt;/a&gt; adiciona e remove réplicas da API conforme uma métrica, normalmente CPU. A premissa é que &lt;span class=&quot;caneta caneta-riscado&quot;&gt;&lt;s&gt;CPU alta significa mais usuários&lt;/s&gt;&lt;/span&gt;. Com o batch dentro da API, essa premissa quebra:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;o HPA sobe &lt;span class=&quot;caneta caneta-tendencia&quot;&gt;réplicas&lt;span class=&quot;caneta-tendencia-seta&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (aumenta)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; que nenhum usuário está usando, e você paga por elas. E elas nem ajudam o lote: a mensagem é uma só e já está num pod;&lt;/li&gt;
&lt;li&gt;quando a média de CPU cai, o HPA remove réplicas depois da janela de estabilização (5 minutos por padrão), e o pod removido pode ser justamente o que está com a mensagem: o lote é interrompido como num deploy (ver critério 2);&lt;/li&gt;
&lt;li&gt;a métrica perde significado: não dá mais para saber se a API escalou por demanda real ou por causa do batch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Na abordagem A, o HPA da API continua reagindo só ao tráfego.&lt;/p&gt;
&lt;h3 id=&quot;5-quando-o-destino-cai-retry-dlq-e-redrive&quot;&gt;5. Quando o destino cai: retry, DLQ e redrive&lt;/h3&gt;
&lt;p&gt;Imagine o &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://aws.amazon.com/sns/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;SNS&lt;/span&gt; indisponível por uma hora.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Abordagem B:&lt;/strong&gt; o consumidor tenta publicar, falha, e o processamento para. A mensagem não é apagada: volta à fila depois do visibility timeout, e a nova tentativa segue de onde parou, pelo status no banco, e falha de novo enquanto o SNS estiver fora. Cada tentativa conta um recebimento; atingido o &lt;code&gt;maxReceiveCount&lt;/code&gt; (o limite de recebimentos da &lt;em&gt;redrive policy&lt;/em&gt;), a mensagem, que representa o lote inteiro, vai para a DLQ. O intervalo entre as tentativas é o próprio visibility timeout: se ele foi dimensionado para cobrir o lote (critério 6), uma queda de uma hora pode passar entre duas tentativas; se é curto e o consumidor o estende enquanto processa, as tentativas se esgotam em minutos. Na DLQ, nada retoma sozinho: os pendentes ficam no banco até alguém, ou uma automação, fazer o redrive da mensagem para a fila principal (&lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-dead-letter-queue-redrive.html&quot;&gt;SQS — DLQ redrive&lt;/a&gt;), ou até o próximo disparo. E a DLQ tem prazo: &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;a retenção&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;não zera ao ir para a DLQ&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; conta desde o envio original, então a mensagem esquecida lá expira (&lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html&quot;&gt;SQS — Dead-letter queues&lt;/a&gt;). Ela também não separa as causas: uma queda do SNS e um registro ruim que derruba o consumidor chegam lá do mesmo jeito, como o lote inteiro.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abordagem A:&lt;/strong&gt; o SDK da AWS tenta de novo algumas vezes, com backoff. Esgotadas as tentativas, o step falha no chunk em andamento, o job sai com exit code diferente de zero e os registros ainda não enviados continuam pendentes no banco. As novas tentativas do &lt;code&gt;backoffLimit&lt;/code&gt; não resolvem uma queda longa: o Kubernetes recria o pod com atraso de &lt;span class=&quot;caneta caneta-explica&quot;&gt;&lt;span class=&quot;caneta-explica-alvo&quot;&gt;10 s, 20 s, 40 s…&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-explica-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (quer dizer: &lt;/span&gt;dobra a cada tentativa&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (limitado a seis minutos), então, com &lt;code&gt;backoffLimit: 2&lt;/code&gt;, todas acontecem com o SNS ainda fora. Quem pega os pendentes é a próxima execução agendada (num job diário, até 24 horas depois) ou um disparo manual assim que o SNS voltar: &lt;code&gt;kubectl create job enviar-registros-manual --from=cronjob/enviar-registros&lt;/code&gt;. Não há mensagem parada numa DLQ nem redrive a fazer, mas há atraso. E, se o step usar skip para isolar itens inválidos, a exceção de infraestrutura não pode estar entre as puláveis: senão a queda do SNS vira uma leva de itens pulados (até o &lt;code&gt;skipLimit&lt;/code&gt;), e uma falha de infraestrutura fica registrada como dado ruim.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A figura mostra o mesmo lote nos três cenários, com o SNS fora do ar das 03:20 às 04:20 (a faixa vermelha) e, na B, &lt;code&gt;maxReceiveCount&lt;/code&gt; 3: a A em verde, a B em roxo.&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 540&quot;
  aria-label=&quot;Linha do tempo com o SNS fora do ar das 03:20 às 04:20, no mesmo lote: na A, o Job falha em cerca de um minuto e os pendentes esperam o próximo dia ou um disparo manual; na B com timeout de 2 h, a mensagem fica invisível até as 05:00 e aí retoma; na B com timeout curto, três tentativas falham em minutos e a mensagem vai para a DLQ.&quot;&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;
      &lt;rect x=&quot;407&quot; y=&quot;104&quot; width=&quot;323&quot; height=&quot;340&quot; rx=&quot;4&quot; class=&quot;lavado&quot;/&gt;
    &lt;/g&gt;
    &lt;path d=&quot;M300 88 H1172 M1160 80 L1174 88 L1160 96&quot; class=&quot;eixo&quot;/&gt;
    &lt;path d=&quot;M300 80 V96 M407 80 V96 M730 80 V96 M945 80 V96 M1160 80 V96&quot; class=&quot;eixo&quot;/&gt;

    &lt;g class=&quot;tom-verde&quot;&gt;
      &lt;rect x=&quot;300&quot; y=&quot;160&quot; width=&quot;107&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;300&quot; y=&quot;160&quot; width=&quot;107&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;480&quot; y=&quot;160&quot; width=&quot;680&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;480&quot; y=&quot;160&quot; width=&quot;680&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;fantasma&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;
      &lt;rect x=&quot;300&quot; y=&quot;260&quot; width=&quot;107&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;300&quot; y=&quot;260&quot; width=&quot;107&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;440&quot; y=&quot;260&quot; width=&quot;505&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;440&quot; y=&quot;260&quot; width=&quot;505&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;945&quot; y=&quot;260&quot; width=&quot;215&quot; height=&quot;50&quot; rx=&quot;6&quot; transform=&quot;translate(6 5)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;945&quot; y=&quot;260&quot; width=&quot;215&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;945&quot; y=&quot;260&quot; width=&quot;215&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;300&quot; y=&quot;360&quot; width=&quot;107&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;300&quot; y=&quot;360&quot; width=&quot;107&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;486&quot; y=&quot;366&quot; width=&quot;72&quot; height=&quot;38&quot; rx=&quot;5&quot; transform=&quot;translate(5 4)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;486&quot; y=&quot;366&quot; width=&quot;72&quot; height=&quot;38&quot; rx=&quot;5&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;486&quot; y=&quot;366&quot; width=&quot;72&quot; height=&quot;38&quot; rx=&quot;5&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;570&quot; y=&quot;360&quot; width=&quot;590&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;papel&quot;/&gt;
      &lt;rect x=&quot;570&quot; y=&quot;360&quot; width=&quot;590&quot; height=&quot;50&quot; rx=&quot;6&quot; class=&quot;fantasma&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;
      &lt;path d=&quot;M414 178 l14 14 m0 -14 l-14 14 M436 178 l14 14 m0 -14 l-14 14 M458 178 l14 14 m0 -14 l-14 14&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M416 278 l14 14 m0 -14 l-14 14&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M414 378 l14 14 m0 -14 l-14 14 M436 378 l14 14 m0 -14 l-14 14 M458 378 l14 14 m0 -14 l-14 14&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-vermelho&quot;&gt;
    &lt;circle cx=&quot;569&quot; cy=&quot;129&quot; r=&quot;7&quot; class=&quot;selo pisca&quot;/&gt;
  &lt;/g&gt;

  &lt;text x=&quot;300&quot; y=&quot;66&quot; text-anchor=&quot;middle&quot; class=&quot;valor-eixo&quot;&gt;03:00&lt;/text&gt;
  &lt;text x=&quot;407&quot; y=&quot;66&quot; text-anchor=&quot;middle&quot; class=&quot;valor-eixo&quot;&gt;03:20&lt;/text&gt;
  &lt;text x=&quot;730&quot; y=&quot;66&quot; text-anchor=&quot;middle&quot; class=&quot;valor-eixo&quot;&gt;04:20&lt;/text&gt;
  &lt;text x=&quot;945&quot; y=&quot;66&quot; text-anchor=&quot;middle&quot; class=&quot;valor-eixo&quot;&gt;05:00&lt;/text&gt;
  &lt;text x=&quot;1160&quot; y=&quot;66&quot; text-anchor=&quot;middle&quot; class=&quot;valor-eixo&quot;&gt;05:40&lt;/text&gt;
  &lt;g class=&quot;tom-vermelho&quot;&gt;
    &lt;text x=&quot;584&quot; y=&quot;136&quot; class=&quot;texto-tom nota-pequena&quot;&gt;SNS fora do ar&lt;/text&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;text x=&quot;280&quot; y=&quot;180&quot; text-anchor=&quot;end&quot; class=&quot;texto-tom rotulo&quot;&gt;A: CronJob&lt;/text&gt;
    &lt;text x=&quot;280&quot; y=&quot;206&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;backoffLimit: 2&lt;/text&gt;
    &lt;text x=&quot;280&quot; y=&quot;230&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;3 tentativas em ~1 min&lt;/text&gt;
    &lt;text x=&quot;353&quot; y=&quot;192&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;processa&lt;/text&gt;
    &lt;text x=&quot;820&quot; y=&quot;192&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;o Job falha; os pendentes esperam o próximo dia ou um disparo manual&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;text x=&quot;280&quot; y=&quot;280&quot; text-anchor=&quot;end&quot; class=&quot;texto-tom rotulo&quot;&gt;B: timeout de 2 h&lt;/text&gt;
    &lt;text x=&quot;280&quot; y=&quot;306&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;cobre o lote&lt;/text&gt;
    &lt;text x=&quot;353&quot; y=&quot;292&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;processa&lt;/text&gt;
    &lt;text x=&quot;692&quot; y=&quot;292&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;mensagem invisível até 05:00, 2 h desde o recebimento&lt;/text&gt;
    &lt;text x=&quot;1052&quot; y=&quot;292&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;retoma e termina&lt;/text&gt;
    &lt;text x=&quot;280&quot; y=&quot;380&quot; text-anchor=&quot;end&quot; class=&quot;texto-tom rotulo&quot;&gt;B: timeout de 1 min&lt;/text&gt;
    &lt;text x=&quot;280&quot; y=&quot;406&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;estendido enquanto processa&lt;/text&gt;
    &lt;text x=&quot;280&quot; y=&quot;430&quot; text-anchor=&quot;end&quot; class=&quot;nota-pequena&quot;&gt;3 tentativas em ~3 min&lt;/text&gt;
    &lt;text x=&quot;353&quot; y=&quot;392&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;processa&lt;/text&gt;
    &lt;text x=&quot;522&quot; y=&quot;392&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;DLQ&lt;/text&gt;
    &lt;text x=&quot;865&quot; y=&quot;392&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;os pendentes esperam o redrive da DLQ ou o próximo disparo&lt;/text&gt;
  &lt;/g&gt;
  &lt;text x=&quot;600&quot; y=&quot;490&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;Nos três casos o estado fica no banco e nenhum pendente se perde:&lt;/text&gt;
  &lt;text x=&quot;600&quot; y=&quot;522&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;o que muda é quem retoma, e quando.&lt;/text&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;O desfecho depende do intervalo entre as tentativas; nos três casos, os pendentes ficam no banco.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Na B, dá para controlar o intervalo entre as tentativas: o Spring Cloud AWS traz um &lt;code&gt;ExponentialBackoffErrorHandler&lt;/code&gt;, que, a cada falha, muda o visibility timeout da mensagem para um valor que cresce com o número de entregas, e dá para automatizar o redrive. Mas é desenho e código a mais, e o backoff precisa ser dimensionado junto com o &lt;code&gt;maxReceiveCount&lt;/code&gt;. Há ainda o risco de retry em várias camadas ao mesmo tempo: SDK, eventual retry no listener e reentrega da fila. O artigo &lt;a href=&quot;https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/&quot;&gt;Timeouts, retries, and backoff with jitter&lt;/a&gt;, da Amazon Builders’ Library, recomenda concentrar o retry &lt;span class=&quot;caneta caneta-duplo&quot;&gt;num único ponto da pilha&lt;/span&gt;, porque cada camada extra multiplica a carga sobre quem já está com problema.&lt;/p&gt;
&lt;h3 id=&quot;6-uma-mensagem-para-o-lote-inteiro&quot;&gt;6. Uma mensagem para o lote inteiro&lt;/h3&gt;
&lt;p&gt;Na abordagem B, a mensagem é só o gatilho: “processe os pendentes”. Quem sabe o que já foi feito é o banco, e quem lê a lista é o consumidor, não o endpoint. O desenho é simples, mas o lote inteiro &lt;span class=&quot;caneta caneta-duplo&quot;&gt;fica preso a uma mensagem&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Um pod só.&lt;/strong&gt; O lote roda inteiro no pod que recebeu a mensagem, que continua atendendo a sua parte das requisições (critério 1). As outras réplicas não têm o que consumir, então não há paralelismo entre pods.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O visibility timeout precisa cobrir o lote.&lt;/strong&gt; Enquanto o consumidor trabalha, a mensagem continua na fila, só invisível para os outros. Se o prazo vence antes do fim, ela volta a ficar visível, outro consumidor a recebe e começa o mesmo lote: dois consumidores lendo os mesmos pendentes ao mesmo tempo. O padrão da fila é 30 segundos, e o Spring Cloud AWS, numa fila standard, define a visibilidade uma vez só, no recebimento (&lt;a href=&quot;https://github.com/awspring/spring-cloud-aws/blob/v4.1.1/docs/src/main/asciidoc/sqs.adoc&quot;&gt;Spring Cloud AWS — SQS&lt;/a&gt;). Ou o prazo da fila cobre o lote inteiro, ou o consumidor o estende enquanto processa (o argumento &lt;code&gt;Visibility&lt;/code&gt; do listener tem o método &lt;code&gt;changeTo()&lt;/code&gt;). E há um teto: &lt;span class=&quot;caneta caneta-circulo&quot;&gt;12&lt;/span&gt; horas contadas a partir do recebimento, que as extensões não renovam (&lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html&quot;&gt;SQS — Visibility timeout&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A retomada espera o prazo.&lt;/strong&gt; Se o pod morre (deploy, OOM, redução do HPA), a mensagem só reaparece quando o visibility timeout expira. Um prazo longo, para cobrir o lote, atrasa a retomada na mesma medida; um curto, estendido enquanto processa, retoma logo, mas é código a mais.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Um registro ruim trava o lote.&lt;/strong&gt; Se o consumidor lança exceção num registro, a mensagem inteira volta à fila e, depois de N tentativas, vai para a DLQ, parando no mesmo registro a cada vez. O consumidor precisa marcar o registro inválido e seguir, como a abordagem A também precisa (skip ou status).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Na abordagem A, o pod do job é a própria execução, sem prazo de visibilidade para dimensionar, e o reader do Spring Batch lê a lista em páginas, por chave (ver critério 11).&lt;/p&gt;
&lt;h3 id=&quot;7-um-endpoint-a-mais-para-proteger&quot;&gt;7. Um endpoint a mais para proteger&lt;/h3&gt;
&lt;div class=&quot;caneta-margem caneta-asterisco&quot;&gt;&lt;p&gt;Na abordagem B existe uma rota HTTP que dispara processamento em lote. Ela precisa ser protegida, e o CronJob, se autenticar para chamá-la: obter um token e montar a requisição, geralmente num script shell. Em ambientes regulados, expor lógica de negócio como endpoint pode não ser permitido. É esse o argumento de Chris Jones, no artigo já citado, para trocar o CronJob que chama a API via &lt;code&gt;curl&lt;/code&gt; por um CronJob que roda a própria imagem (&lt;a href=&quot;https://thenewstack.io/rethinking-java-scheduled-tasks-in-kubernetes/&quot;&gt;The New Stack&lt;/a&gt;).&lt;/p&gt;&lt;/div&gt;
&lt;h3 id=&quot;8-visibilidade-por-execução&quot;&gt;8. Visibilidade por execução&lt;/h3&gt;
&lt;p&gt;Na abordagem A, cada execução é um objeto com início, fim e resultado:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;o exit code do container diz ao Kubernetes se o pod deu certo e, esgotadas as tentativas do &lt;code&gt;backoffLimit&lt;/code&gt;, o Job fica como falho. O kube-state-metrics transforma isso em métricas, sem código adicional: &lt;code&gt;kube_job_failed{condition=&amp;quot;true&amp;quot;}&lt;/code&gt; indica o Job que falhou de vez. Não use &lt;span class=&quot;caneta caneta-riscado com-correcao&quot;&gt;&lt;s&gt;&lt;code&gt;kube_job_status_failed&lt;/code&gt;&lt;/s&gt;&lt;span class=&quot;caneta-escrita caneta-correcao&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (correção: &lt;/span&gt;use kube_job_failed&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; para esse alerta: ela conta pods com falha e passa de zero mesmo quando a retentativa deu certo (&lt;a href=&quot;https://github.com/kubernetes/kube-state-metrics/blob/main/docs/metrics/workload/job-metrics.md&quot;&gt;kube-state-metrics — métricas de Job&lt;/a&gt;);&lt;/li&gt;
&lt;li&gt;falha não é o único risco: se o CronJob não criar o Job, ou se o &lt;code&gt;Forbid&lt;/code&gt; pular horários atrás de um Job travado, nenhum Job falha e nenhum alerta de falha dispara. Para isso serve &lt;code&gt;kube_cronjob_status_last_successful_time&lt;/code&gt;, o horário do último sucesso: &lt;code&gt;time() - kube_cronjob_status_last_successful_time{cronjob=&amp;quot;enviar-registros&amp;quot;} &amp;gt; 26 * 3600&lt;/code&gt; avisa quando o job diário passa mais de &lt;span class=&quot;caneta caneta-explica&quot;&gt;&lt;span class=&quot;caneta-explica-alvo&quot;&gt;26 horas&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-explica-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (quer dizer: &lt;/span&gt;um dia + 2 h de folga&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; sem terminar com sucesso (&lt;a href=&quot;https://github.com/kubernetes/kube-state-metrics/blob/main/docs/metrics/workload/cronjob-metrics.md&quot;&gt;kube-state-metrics — métricas de CronJob&lt;/a&gt;);&lt;/li&gt;
&lt;li&gt;o Spring Batch grava cada execução nas tabelas de metadados, desde que o JobRepository esteja no banco (ver &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/#como-montar-a-abordagem-a&quot;&gt;Como montar a abordagem A&lt;/a&gt;). &lt;code&gt;BATCH_JOB_EXECUTION&lt;/code&gt; guarda início, fim e status. &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;BATCH_STEP_EXECUTION&lt;/code&gt;&lt;/span&gt; guarda quantos itens foram lidos (&lt;code&gt;READ_COUNT&lt;/code&gt;), gravados (&lt;code&gt;WRITE_COUNT&lt;/code&gt;), filtrados (&lt;code&gt;FILTER_COUNT&lt;/code&gt;) e pulados (&lt;code&gt;READ_SKIP_COUNT&lt;/code&gt;, &lt;code&gt;PROCESS_SKIP_COUNT&lt;/code&gt;, &lt;code&gt;WRITE_SKIP_COUNT&lt;/code&gt;) (&lt;a href=&quot;https://docs.spring.io/spring-batch/reference/schema-appendix.html&quot;&gt;Spring Batch — Meta-Data Schema&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Na abordagem B, a fila só mostra o gatilho: se a mensagem foi consumida, se voltou, se foi para a DLQ. Responder “O lote de hoje terminou? Quantos registros foram enviados?” exige criar tabela, contadores e lógica próprios. Não é impossível; é trabalho que, na abordagem A, já vem pronto.&lt;/p&gt;
&lt;h3 id=&quot;9-resposta-perdida-na-rede-o-gatilho-dispara-duas-vezes&quot;&gt;9. Resposta perdida na rede: o gatilho dispara duas vezes&lt;/h3&gt;
&lt;p&gt;Na abordagem B, entre o agendador e o processamento existe uma chamada HTTP, e chamadas HTTP falham de um jeito traiçoeiro. O endpoint recebe a requisição, publica a mensagem e responde &lt;code&gt;202&lt;/code&gt;, mas &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;a resposta se perde no caminho&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;o 202 nunca chega ao curl&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: timeout do próprio &lt;code&gt;curl&lt;/code&gt;, conexão resetada porque o pod que recebeu a chamada está sendo encerrado num deploy, um proxy no meio. O &lt;code&gt;curl&lt;/code&gt; termina com erro, o pod do CronJob sai com exit code diferente de zero e o Kubernetes, seguindo o &lt;code&gt;backoffLimit&lt;/code&gt;, tenta de novo. O endpoint recebe a segunda chamada e publica uma segunda mensagem. Se houver retry configurado em algum proxy intermediário, como ingress ou service mesh, a requisição pode ser reenviada sem que o CronJob sequer perceba.&lt;/p&gt;
&lt;p&gt;No diagrama de sequência, o tempo corre de cima para baixo, e os pontos seguem as mensagens na ordem em que acontecem.&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 1000&quot;
  aria-label=&quot;Diagrama de sequência da abordagem B: o CronJob faz POST /processar, o endpoint publica a mensagem 1, que vira a execução 1; a resposta 202 se perde, o curl sai com erro, o Kubernetes tenta de novo, e a segunda chamada publica a mensagem 2, que vira a execução 2 com a 1 ainda rodando: os mesmos registros saem duas vezes no SNS.&quot;&gt;
  &lt;path d=&quot;M150 124 V868 M450 124 V868 M750 124 V868 M1050 124 V868&quot; class=&quot;grade&quot;/&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;tom-azul&quot;&gt;
      &lt;rect x=&quot;32&quot; y=&quot;37&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M150 175 H436 M422 166 L436 175 L422 184&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;440&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;440&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;516&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;516&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M150 630 H436 M422 621 L436 630 L422 639&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-ambar&quot;&gt;
      &lt;rect x=&quot;332&quot; y=&quot;37&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;325&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;325&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;932&quot; y=&quot;37&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M450 230 H736 M722 221 L736 230 L722 239&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M450 395 H198&quot; class=&quot;fantasma&quot;/&gt;
      &lt;path d=&quot;M450 685 H736 M722 676 L736 685 L722 694&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M450 740 H166&quot; class=&quot;fantasma&quot;/&gt;
      &lt;path d=&quot;M178 731 L164 740 L178 749&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;306&quot; width=&quot;250&quot; height=&quot;52&quot; rx=&quot;8&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;306&quot; width=&quot;250&quot; height=&quot;52&quot; rx=&quot;8&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-roxo&quot;&gt;
      &lt;rect x=&quot;625&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;625&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;625&quot; y=&quot;30&quot; width=&quot;250&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M750 285 H1036 M1022 276 L1036 285 L1022 294&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M750 795 H1036 M1022 786 L1036 795 L1022 804&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;
      &lt;path d=&quot;M168 386 l18 18 m0 -18 l-18 18&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;815&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; transform=&quot;translate(6 5)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;815&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;925&quot; y=&quot;815&quot; width=&quot;250&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;910&quot; width=&quot;1150&quot; height=&quot;74&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;910&quot; width=&quot;1150&quot; height=&quot;74&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-ambar&quot;&gt;
      &lt;path d=&quot;M1162 358 V815&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;path d=&quot;M152 175 H430&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
    &lt;path d=&quot;M152 630 H430&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-5&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;path d=&quot;M452 230 H730&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-2&quot;/&gt;
    &lt;path d=&quot;M448 395 H200&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-4&quot;/&gt;
    &lt;path d=&quot;M452 685 H730&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-6&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;path d=&quot;M752 285 H1030&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-3&quot;/&gt;
    &lt;path d=&quot;M752 795 H1030&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-7&quot;/&gt;
  &lt;/g&gt;

  &lt;g transform=&quot;translate(40 50) scale(0.48)&quot; class=&quot;marca marca-kubernetes tom-azul&quot;&gt;&lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M71 51.6 A21 21 0 1 1 29 51.6 A21 21 0 1 1 71 51.6 Z M65 51.6 A15 15 0 1 0 35 51.6 A15 15 0 1 0 65 51.6 Z&quot; fill-rule=&quot;evenodd&quot;/&gt;
    &lt;circle cx=&quot;50&quot; cy=&quot;51.6&quot; r=&quot;5.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(51.43 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(102.86 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(154.29 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(205.71 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(257.14 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(308.57 50 51.6)&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(340 52) scale(0.42)&quot; class=&quot;marca marca-spring tom-ambar&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(638 50) scale(0.48)&quot; class=&quot;marca marca-sqs tom-roxo&quot;&gt;&lt;g class=&quot;tinta tom-roxo&quot;&gt;
    &lt;path d=&quot;M38 36 Q50 43 62 36 Q55 50 62 64 Q50 57 38 64 Q45 50 38 36 Z&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M38 36 Q50 43 62 36 Q55 50 62 64 Q50 57 38 64 Q45 50 38 36 Z&quot; class=&quot;linha&quot;/&gt;
    &lt;path d=&quot;M15.6 33.9 A38 38 0 0 1 84.4 33.9 M15.6 66.1 A38 38 0 0 0 84.4 66.1&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M22 50 H33 M29 45 L34 50 L29 55 M66 50 H77 M73 45 L78 50 L73 55&quot; class=&quot;linha&quot;/&gt;
    &lt;circle cx=&quot;12&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;88&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(940 52) scale(0.42)&quot; class=&quot;marca marca-spring tom-ambar&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(56 924) scale(0.46)&quot; class=&quot;marca marca-sns tom-vermelho&quot;&gt;&lt;g class=&quot;tinta tom-roxo&quot;&gt;
    &lt;circle cx=&quot;48&quot; cy=&quot;50&quot; r=&quot;36&quot; class=&quot;lavado&quot;/&gt;
    &lt;path d=&quot;M70.2 21.6 A36 36 0 1 0 70.2 78.4&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;path d=&quot;M28 38 H54 L45 53 V64 L37 60 V53 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M17 50 H33 M48 50 H64 M64 28 V72 M64 28 H76 M64 72 H76 M64 50 H80&quot; class=&quot;linha&quot;/&gt;
    &lt;circle cx=&quot;12&quot; cy=&quot;50&quot; r=&quot;6&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;82&quot; cy=&quot;28&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;86&quot; cy=&quot;50&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;circle cx=&quot;82&quot; cy=&quot;72&quot; r=&quot;7&quot; class=&quot;cheio-tom&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;text x=&quot;100&quot; y=&quot;72&quot; class=&quot;titulo-caixa&quot;&gt;CronJob&lt;/text&gt;
    &lt;text x=&quot;100&quot; y=&quot;102&quot; class=&quot;texto-caixa&quot;&gt;com curl&lt;/text&gt;
    &lt;text x=&quot;293&quot; y=&quot;160&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;POST /processar&lt;/text&gt;
    &lt;text x=&quot;150&quot; y=&quot;467&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;timeout: o curl&lt;/text&gt;
    &lt;text x=&quot;150&quot; y=&quot;491&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;sai com erro&lt;/text&gt;
    &lt;text x=&quot;150&quot; y=&quot;543&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;o Kubernetes tenta&lt;/text&gt;
    &lt;text x=&quot;150&quot; y=&quot;567&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;de novo (backoffLimit)&lt;/text&gt;
    &lt;text x=&quot;293&quot; y=&quot;615&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;POST /processar&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;text x=&quot;394&quot; y=&quot;72&quot; class=&quot;titulo-caixa&quot;&gt;Endpoint&lt;/text&gt;
    &lt;text x=&quot;394&quot; y=&quot;102&quot; class=&quot;texto-caixa&quot;&gt;da API&lt;/text&gt;
    &lt;text x=&quot;994&quot; y=&quot;72&quot; class=&quot;titulo-caixa&quot;&gt;Listener&lt;/text&gt;
    &lt;text x=&quot;994&quot; y=&quot;102&quot; class=&quot;texto-caixa&quot;&gt;nos pods da API&lt;/text&gt;
    &lt;text x=&quot;593&quot; y=&quot;216&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;publica a mensagem 1&lt;/text&gt;
    &lt;text x=&quot;1050&quot; y=&quot;339&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;execução 1 começa o lote&lt;/text&gt;
    &lt;text x=&quot;593&quot; y=&quot;671&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;publica a mensagem 2&lt;/text&gt;
    &lt;text x=&quot;308&quot; y=&quot;726&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;202 Accepted&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-roxo&quot;&gt;
    &lt;text x=&quot;700&quot; y=&quot;72&quot; class=&quot;titulo-caixa&quot;&gt;Fila SQS&lt;/text&gt;
    &lt;text x=&quot;700&quot; y=&quot;102&quot; class=&quot;texto-caixa&quot;&gt;standard&lt;/text&gt;
    &lt;text x=&quot;893&quot; y=&quot;271&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;entrega a mensagem 1&lt;/text&gt;
    &lt;text x=&quot;893&quot; y=&quot;781&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;entrega a mensagem 2&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-vermelho&quot;&gt;
    &lt;text x=&quot;318&quot; y=&quot;356&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;202 Accepted,&lt;/text&gt;
    &lt;text x=&quot;318&quot; y=&quot;380&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;mas a resposta se perde&lt;/text&gt;
    &lt;text x=&quot;1050&quot; y=&quot;843&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;execução 2: o mesmo lote,&lt;/text&gt;
    &lt;text x=&quot;1050&quot; y=&quot;867&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;com a 1 ainda rodando&lt;/text&gt;
    &lt;text x=&quot;118&quot; y=&quot;942&quot; class=&quot;texto-tom texto-caixa&quot;&gt;Duas execuções do mesmo lote ao mesmo tempo:&lt;/text&gt;
    &lt;text x=&quot;118&quot; y=&quot;970&quot; class=&quot;nota-pequena&quot;&gt;em pods diferentes ou no mesmo pod, os registros que as duas leem como pendentes saem duas vezes no SNS.&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-ambar&quot;&gt;
    &lt;text x=&quot;1150&quot; y=&quot;600&quot; text-anchor=&quot;end&quot; class=&quot;texto-tom nota-pequena&quot;&gt;a 1 segue&lt;/text&gt;
  &lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;A resposta perdida faz o CronJob chamar de novo, e a segunda mensagem abre uma segunda execução do mesmo lote.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Isso pressupõe um &lt;code&gt;curl&lt;/code&gt; bem configurado. Sem &lt;code&gt;--fail&lt;/code&gt;, ele sai com código 0 mesmo quando a API responde 500 ou 401, e o CronJob registra sucesso sem o lote ter rodado; sem &lt;code&gt;--max-time&lt;/code&gt;, ele não tem prazo para desistir. Use &lt;code&gt;curl --fail --max-time &amp;lt;segundos&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-colchete&quot;&gt;&lt;p&gt;O problema é estrutural: quem chama não consegue distinguir “a requisição não chegou” de “a requisição chegou, mas a resposta não voltou”. A &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://aws.amazon.com/builders-library/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Amazon Builders’ Library&lt;/span&gt; descreve exatamente esse dilema: depois de um timeout, quem chamou não sabe se a operação aconteceu, e repetir a chamada pode duplicar o efeito. A saída é tornar a operação idempotente (&lt;a href=&quot;https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/&quot;&gt;Making retries safe with idempotent APIs&lt;/a&gt;). Na abordagem B, isso significa uma &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;chave de idempotência&lt;/a&gt;, como a data de referência. No gatilho, uma fila FIFO resolve parte do problema: com o &lt;code&gt;MessageDeduplicationId&lt;/code&gt; igual à data, uma segunda mensagem enviada em até 5 minutos é aceita, mas não é entregue, o que cobre o retry rápido do Kubernetes, mas não uma nova chamada mais tarde (&lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues-exactly-once-processing.html&quot;&gt;SQS — Exactly-once processing&lt;/a&gt;). O resto fica com o consumidor.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;A coluna de status no banco ajuda, &lt;span class=&quot;caneta caneta-duplo&quot;&gt;mas não resolve sozinha&lt;/span&gt;. Se a segunda mensagem chega depois que a primeira terminou, não encontra pendentes e não faz nada. O problema é quando as duas rodam juntas, que é justamente o caso do retry rápido: dois pods leem os mesmos registros como pendentes antes que qualquer um marque “enviado”, e cada registro sai duas vezes. Evitar isso exige que o consumidor reserve cada registro com uma &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/#4-o-update-condicional-que-muitas-vezes-dispensa-os-dois&quot;&gt;atualização condicional&lt;/a&gt; antes de enviar, ou que só um consumidor processe o lote por vez, com um lock no banco que expire se o pod morrer (como o do &lt;a href=&quot;https://github.com/lukas-krecan/ShedLock&quot;&gt;ShedLock&lt;/a&gt;). Mais uma peça a construir.&lt;/p&gt;
&lt;p&gt;Na abordagem A, esse modo de falha não aparece, mas não por falta de rede no caminho. O controlador do CronJob também cria o Job com uma chamada ao API server, e essa resposta também pode se perder. A diferença é que o Kubernetes já tornou essa chamada idempotente: &lt;mark class=&quot;caneta-grifo&quot;&gt;o nome do Job é derivado do horário agendado&lt;/mark&gt;, e uma nova tentativa para o mesmo horário recebe &lt;code&gt;AlreadyExists&lt;/code&gt; em vez de criar outro Job (&lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/cronjob/utils.go&quot;&gt;código do controlador&lt;/a&gt;). É a chave de idempotência que a abordagem B teria de construir. Dali em diante, o processamento é o próprio pod, e o resultado é o exit code dele, sem resposta HTTP no meio. O que sobra são os casos raros documentados (critério 10), barrados pelo JobRepository.&lt;/p&gt;
&lt;p&gt;O mesmo diagrama, na abordagem A:&lt;/p&gt;
&lt;figure class=&quot;figura&quot; data-pagefind-ignore data-figura-viva&gt;&lt;div class=&quot;figura-palco painel&quot;&gt;&lt;svg class=&quot;ilustracao diagrama&quot; role=&quot;img&quot; focusable=&quot;false&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 1200 960&quot;
  aria-label=&quot;Diagrama de sequência da abordagem A: o CronJob cria o Job enviar-registros-29837160, com nome derivado do horário; a resposta 201 se perde, a nova tentativa usa o mesmo nome e recebe 409 AlreadyExists; o Job já criado sobe um pod só, que registra a execução do dia no JobRepository, processa o lote e termina com exit code 0.&quot;&gt;
  &lt;path d=&quot;M130 124 V800 M560 124 V800 M835 124 V800 M1073 124 V800&quot; class=&quot;grade&quot;/&gt;
  &lt;g class=&quot;tinta&quot;&gt;
    &lt;g class=&quot;tom-azul&quot;&gt;
      &lt;rect x=&quot;27&quot; y=&quot;37&quot; width=&quot;225&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;20&quot; y=&quot;30&quot; width=&quot;225&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;20&quot; y=&quot;30&quot; width=&quot;225&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;427&quot; y=&quot;37&quot; width=&quot;280&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
      &lt;rect x=&quot;420&quot; y=&quot;30&quot; width=&quot;280&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;420&quot; y=&quot;30&quot; width=&quot;280&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M130 225 H546 M532 216 L546 225 L532 234&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M560 300 H180&quot; class=&quot;fantasma&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;330&quot; width=&quot;200&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;30&quot; y=&quot;330&quot; width=&quot;200&quot; height=&quot;64&quot; rx=&quot;8&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M130 480 H546 M532 471 L546 480 L532 489&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;path d=&quot;M560 548 H146&quot; class=&quot;fantasma&quot;/&gt;
      &lt;path d=&quot;M158 539 L144 548 L158 557&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M560 612 H821 M807 603 L821 612 L807 621&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
    &lt;g class=&quot;tom-verde&quot;&gt;
      &lt;rect x=&quot;722&quot; y=&quot;30&quot; width=&quot;215&quot; height=&quot;88&quot; rx=&quot;12&quot; transform=&quot;translate(7 6)&quot; class=&quot;cor&quot;/&gt;
      &lt;rect x=&quot;722&quot; y=&quot;30&quot; width=&quot;215&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;722&quot; y=&quot;30&quot; width=&quot;215&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M835 672 H1059 M1045 663 L1059 672 L1045 681&quot; class=&quot;linha-tom&quot;/&gt;
      &lt;rect x=&quot;700&quot; y=&quot;692&quot; width=&quot;270&quot; height=&quot;52&quot; rx=&quot;8&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;700&quot; y=&quot;692&quot; width=&quot;270&quot; height=&quot;52&quot; rx=&quot;8&quot; class=&quot;linha&quot;/&gt;
      &lt;path d=&quot;M835 790 H576&quot; class=&quot;fantasma&quot;/&gt;
      &lt;path d=&quot;M588 781 L574 790 L588 799&quot; class=&quot;linha&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;830&quot; width=&quot;1150&quot; height=&quot;110&quot; rx=&quot;12&quot; class=&quot;lavado&quot;/&gt;
      &lt;rect x=&quot;25&quot; y=&quot;830&quot; width=&quot;1150&quot; height=&quot;110&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
    &lt;/g&gt;
    &lt;rect x=&quot;962&quot; y=&quot;37&quot; width=&quot;236&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;hachura&quot;/&gt;
    &lt;rect x=&quot;955&quot; y=&quot;30&quot; width=&quot;236&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;papel&quot;/&gt;
    &lt;rect x=&quot;955&quot; y=&quot;30&quot; width=&quot;236&quot; height=&quot;88&quot; rx=&quot;12&quot; class=&quot;linha&quot;/&gt;
    &lt;g class=&quot;tom-vermelho&quot;&gt;
      &lt;path d=&quot;M152 291 l18 18 m0 -18 l-18 18&quot; class=&quot;linha-tom&quot;/&gt;
    &lt;/g&gt;
  &lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;path d=&quot;M132 225 H540&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-1&quot;/&gt;
    &lt;path d=&quot;M558 300 H182&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-2&quot;/&gt;
    &lt;path d=&quot;M132 480 H540&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-3&quot;/&gt;
    &lt;path d=&quot;M558 548 H152&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-4&quot;/&gt;
    &lt;path d=&quot;M562 612 H815&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-5&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;path d=&quot;M837 672 H1053&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-6&quot;/&gt;
    &lt;path d=&quot;M833 790 H580&quot; pathLength=&quot;1&quot; class=&quot;pacote etapa-7&quot;/&gt;
  &lt;/g&gt;

  &lt;g transform=&quot;translate(34 50) scale(0.48)&quot; class=&quot;marca marca-kubernetes tom-azul&quot;&gt;&lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M71 51.6 A21 21 0 1 1 29 51.6 A21 21 0 1 1 71 51.6 Z M65 51.6 A15 15 0 1 0 35 51.6 A15 15 0 1 0 65 51.6 Z&quot; fill-rule=&quot;evenodd&quot;/&gt;
    &lt;circle cx=&quot;50&quot; cy=&quot;51.6&quot; r=&quot;5.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(51.43 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(102.86 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(154.29 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(205.71 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(257.14 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(308.57 50 51.6)&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(432 50) scale(0.48)&quot; class=&quot;marca marca-kubernetes tom-azul&quot;&gt;&lt;g class=&quot;tinta tom-azul&quot;&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M43.2 9.4 Q50 6.1 56.8 9.4 L78.8 20 Q85.6 23.2 87.2 30.5 L92.7 54.4 Q94.4 61.7 89.7 67.6 L74.4 86.7 Q69.7 92.6 62.2 92.6 L37.8 92.6 Q30.3 92.6 25.6 86.7 L10.3 67.6 Q5.6 61.7 7.3 54.4 L12.8 30.5 Q14.4 23.2 21.2 20 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M71 51.6 A21 21 0 1 1 29 51.6 A21 21 0 1 1 71 51.6 Z M65 51.6 A15 15 0 1 0 35 51.6 A15 15 0 1 0 65 51.6 Z&quot; fill-rule=&quot;evenodd&quot;/&gt;
    &lt;circle cx=&quot;50&quot; cy=&quot;51.6&quot; r=&quot;5.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(51.43 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(102.86 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(154.29 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(205.71 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(257.14 50 51.6)&quot;/&gt;
    &lt;rect x=&quot;47.4&quot; y=&quot;18.2&quot; width=&quot;5.2&quot; height=&quot;33.4&quot; rx=&quot;2.6&quot; transform=&quot;rotate(308.57 50 51.6)&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;
  &lt;g transform=&quot;translate(735 52) scale(0.42)&quot; class=&quot;marca marca-spring tom-verde&quot;&gt;&lt;g class=&quot;tinta tom-verde&quot;&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;cheio-tom&quot;/&gt;
    &lt;path d=&quot;M14 88 C 6 50 34 14 90 9 C 94 62 64 94 14 88 Z&quot; class=&quot;linha&quot;/&gt;
  &lt;/g&gt;
  &lt;g class=&quot;papel&quot;&gt;
    &lt;path d=&quot;M17 86 C 36 74 56 54 74 27 C 75.5 25 78.5 26.5 77.2 28.8 C 60 58 40 78 19.5 89.2 Z&quot;/&gt;
  &lt;/g&gt;&lt;/g&gt;

  &lt;g class=&quot;tom-azul&quot;&gt;
    &lt;text x=&quot;90&quot; y=&quot;72&quot; class=&quot;titulo-caixa&quot;&gt;CronJob&lt;/text&gt;
    &lt;text x=&quot;90&quot; y=&quot;102&quot; class=&quot;texto-caixa&quot;&gt;controlador&lt;/text&gt;
    &lt;text x=&quot;490&quot; y=&quot;72&quot; class=&quot;titulo-caixa&quot;&gt;API do&lt;/text&gt;
    &lt;text x=&quot;490&quot; y=&quot;102&quot; class=&quot;texto-caixa&quot;&gt;Kubernetes&lt;/text&gt;
    &lt;text x=&quot;345&quot; y=&quot;168&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;cria o Job&lt;/text&gt;
    &lt;text x=&quot;345&quot; y=&quot;206&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;enviar-registros-29837160&lt;/text&gt;
    &lt;text x=&quot;345&quot; y=&quot;252&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;o horário agendado, em minutos desde 1970&lt;/text&gt;
    &lt;text x=&quot;130&quot; y=&quot;356&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;nova tentativa para&lt;/text&gt;
    &lt;text x=&quot;130&quot; y=&quot;380&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;o mesmo horário&lt;/text&gt;
    &lt;text x=&quot;345&quot; y=&quot;424&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;cria o Job&lt;/text&gt;
    &lt;text x=&quot;345&quot; y=&quot;462&quot; text-anchor=&quot;middle&quot; class=&quot;codigo&quot;&gt;enviar-registros-29837160&lt;/text&gt;
    &lt;text x=&quot;345&quot; y=&quot;532&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;409 AlreadyExists: nenhum Job novo&lt;/text&gt;
    &lt;text x=&quot;697&quot; y=&quot;596&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;o Job já criado sobe o pod&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-vermelho&quot;&gt;
    &lt;text x=&quot;360&quot; y=&quot;288&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;201 Created, mas a resposta se perde&lt;/text&gt;
  &lt;/g&gt;
  &lt;g class=&quot;tom-verde&quot;&gt;
    &lt;text x=&quot;779&quot; y=&quot;82&quot; class=&quot;titulo-caixa&quot;&gt;Pod do job&lt;/text&gt;
    &lt;text x=&quot;955&quot; y=&quot;634&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;registra a execução&lt;/text&gt;
    &lt;text x=&quot;955&quot; y=&quot;656&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;do dia&lt;/text&gt;
    &lt;text x=&quot;835&quot; y=&quot;726&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;processa o lote e termina&lt;/text&gt;
    &lt;text x=&quot;680&quot; y=&quot;778&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom nota-pequena&quot;&gt;exit code 0&lt;/text&gt;
    &lt;text x=&quot;600&quot; y=&quot;872&quot; text-anchor=&quot;middle&quot; class=&quot;texto-tom texto-caixa&quot;&gt;Um Job só: o nome derivado do horário é a chave de idempotência.&lt;/text&gt;
    &lt;text x=&quot;600&quot; y=&quot;904&quot; text-anchor=&quot;middle&quot; class=&quot;nota-pequena&quot;&gt;É a chave que a B teria de construir; se um dia surgir um segundo pod para a mesma data, o JobRepository recusa.&lt;/text&gt;
  &lt;/g&gt;
  &lt;text x=&quot;1073&quot; y=&quot;72&quot; text-anchor=&quot;middle&quot; class=&quot;titulo-caixa&quot;&gt;JobRepository&lt;/text&gt;
  &lt;text x=&quot;1073&quot; y=&quot;102&quot; text-anchor=&quot;middle&quot; class=&quot;texto-caixa&quot;&gt;tabelas BATCH_*&lt;/text&gt;
&lt;/svg&gt;
&lt;/div&gt;&lt;p class=&quot;dica-rolar&quot; aria-hidden=&quot;true&quot;&gt;Arraste para o lado para ver a figura inteira.&lt;/p&gt;&lt;figcaption&gt;Na A, a nova tentativa esbarra no nome do Job, que já existe: um Job e um pod só.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;10-outras-fontes-de-duplicidade&quot;&gt;10. Outras fontes de duplicidade&lt;/h3&gt;
&lt;p&gt;Além do gatilho HTTP, há outras fontes de duplicidade, e nem todas dependem da escolha:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O próprio CronJob.&lt;/strong&gt; A documentação do Kubernetes avisa que a criação é aproximada: em certas circunstâncias, um CronJob pode criar &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;dois Jobs, ou nenhum&lt;/span&gt;, e por isso os jobs devem ser idempotentes (&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#job-creation&quot;&gt;Kubernetes — CronJob&lt;/a&gt;). A página de Job acrescenta que, mesmo com um único pod e &lt;code&gt;restartPolicy: Never&lt;/code&gt;, o mesmo programa pode às vezes ser iniciado duas vezes (&lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/job/&quot;&gt;Kubernetes — Jobs&lt;/a&gt;). Na abordagem A, quem cobre isso é o JobRepository do Spring Batch, desde que a data de referência seja o parâmetro identificador do job (ver &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/#como-montar-a-abordagem-a&quot;&gt;Como montar a abordagem A&lt;/a&gt;). Ele recusa uma nova execução de uma instância que já terminou com sucesso ou que ainda está rodando; se a anterior falhou, a nova execução é um restart da mesma instância, que é o que se quer. Se dois pods tentarem criar a mesma instância ao mesmo tempo, só um consegue: a criação roda em transação &lt;code&gt;SERIALIZABLE&lt;/code&gt; (&lt;a href=&quot;https://docs.spring.io/spring-batch/reference/job/configuring-repository.html&quot;&gt;Spring Batch — Configuring a JobRepository&lt;/a&gt;), e a tabela &lt;code&gt;BATCH_JOB_INSTANCE&lt;/code&gt; tem restrição única em (&lt;code&gt;JOB_NAME&lt;/code&gt;, &lt;code&gt;JOB_KEY&lt;/code&gt;). Nos testes, com duas JVMs disparadas juntas para a mesma data, sempre uma processou e a outra saiu com erro, sem publicação duplicada. A execução recusada aparece como Job com falha no Kubernetes: é ruído esperado, não erro. O &lt;code&gt;concurrencyPolicy: Forbid&lt;/code&gt; completa a proteção, impedindo, em regra, que uma execução comece antes de a anterior terminar. Na abordagem B, um segundo Job faz uma segunda chamada ao endpoint, e a proteção é a do critério 9.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A reentrega da fila (só na B).&lt;/strong&gt; A fila standard do SQS entrega cada mensagem &lt;span class=&quot;caneta caneta-explica&quot;&gt;&lt;span class=&quot;caneta-explica-alvo&quot;&gt;pelo menos uma vez&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-explica-nota&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (quer dizer: &lt;/span&gt;at-least-once&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; e, ocasionalmente, mais de uma (&lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html&quot;&gt;SQS — Standard queues&lt;/a&gt;). Com uma mensagem por lote, uma cópia é um segundo consumidor rodando o mesmo lote: o cenário do critério 9, sem nenhuma falha de rede, e com a mesma proteção.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A publicação no SNS.&lt;/strong&gt; Publicar e só depois marcar o registro deixa uma janela: se o processo cair entre as duas operações, o registro é enviado de novo na próxima tentativa. Na B, a janela é de um registro; na A, é do tamanho do chunk: se a transação do chunk é desfeita depois da publicação, todos os itens dele saem de novo. E, com &lt;code&gt;PublishBatch&lt;/code&gt;, a chamada &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;pode voltar 200&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;não quer dizer tudo ok&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; com parte das entradas recusadas, então o writer precisa conferir as falhas da resposta antes de marcar os registros como enviados (&lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/api/API_PublishBatch.html&quot;&gt;Amazon SNS — PublishBatch&lt;/a&gt;). Em qualquer caso, os assinantes do tópico devem ser idempotentes. É a mesma janela do post &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt;, agora com o SNS no lugar do adquirente de pagamentos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;11-retomar-de-onde-parou-empate&quot;&gt;11. Retomar de onde parou: empate&lt;/h3&gt;
&lt;p&gt;As duas abordagens conseguem retomar de onde pararam. Na B, pela reentrega da mensagem e pela coluna de status, que diz o que ainda falta. Na A, pelo padrão &lt;em&gt;process indicator&lt;/em&gt; descrito na documentação do Spring Batch: uma coluna marca os registros processados e o reader traz só os pendentes (&lt;a href=&quot;https://docs.spring.io/spring-batch/reference/readers-and-writers/process-indicator.html&quot;&gt;Spring Batch — Preventing State Persistence&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Dois detalhes fazem esse padrão funcionar. O primeiro é o assunto da própria página citada: o reader deve usar &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;saveState(false)&lt;/code&gt;&lt;/span&gt;. Com o padrão (&lt;code&gt;true&lt;/code&gt;), um reader por cursor, no restart, avança a quantidade de itens já lidos numa consulta que não traz mais os processados, e registros pendentes ficam para trás. O segundo: se a leitura for paginada, pagine por chave, não por offset. O &lt;code&gt;JdbcPagingItemReader&lt;/code&gt; busca cada página a partir da última chave lida (o &lt;code&gt;sortKey&lt;/code&gt;, que precisa ser única); já o &lt;code&gt;JpaPagingItemReader&lt;/code&gt; e o &lt;code&gt;RepositoryItemReader&lt;/code&gt; usam offset, então cada página marcada como enviada sai do filtro, e o offset da página seguinte pula a mesma quantidade de pendentes (&lt;a href=&quot;https://docs.spring.io/spring-batch/reference/readers-and-writers/database.html&quot;&gt;Spring Batch — Database&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-colchete&quot;&gt;&lt;p&gt;A diferença entre as abordagens não está em conseguir retomar, e sim em como cada uma se comporta quando a interrupção vem de um deploy (critério 2) ou de uma indisponibilidade do destino (critério 5).&lt;/p&gt;&lt;/div&gt;
&lt;h2 id=&quot;onde-a-abordagem-b-ganha&quot;&gt;Onde a abordagem B ganha&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Retomada automática.&lt;/strong&gt; Se o consumidor falha ou o pod morre, a mensagem volta sozinha depois do visibility timeout, e outro pod segue de onde parou, pelo status no banco. O Twelve-Factor recomenda exatamente isso para workers, no fator IX (&lt;a href=&quot;https://12factor.net/disposability&quot;&gt;&lt;em&gt;Disposability&lt;/em&gt;&lt;/a&gt;): uma fila que devolva o trabalho quando o processo morre. Na abordagem A, o &lt;code&gt;backoffLimit&lt;/code&gt; retoma uma falha comum, mas um pod morto no meio deixa a execução &lt;code&gt;STARTED&lt;/code&gt;, e as novas tentativas são recusadas até alguém destravá-la (ver “O preço da abordagem A”). O modelo de worker com fila é legítimo; &lt;mark class=&quot;caneta-marca&quot;&gt;o problema é consumi-la dentro da API&lt;/mark&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Um caminho para paralelizar.&lt;/strong&gt; Com uma mensagem por execução, a B também processa o lote num pod só. Mas a fila já está lá: se o volume crescer, o lote pode ser dividido em várias mensagens (por faixa de ids, por exemplo), e os consumidores, escalados pela profundidade da fila, inclusive até zero, com o &lt;a href=&quot;https://keda.sh/docs/2.20/scalers/aws-sqs/&quot;&gt;KEDA&lt;/a&gt;. A abordagem A também paraleliza, mas o grau de paralelismo é definido antes da execução e não cresce sozinho com o volume. No &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/scalability.html&quot;&gt;Spring Batch&lt;/a&gt;, o step multi-thread processa os itens de cada chunk em várias threads dentro do mesmo pod, enquanto a leitura e a escrita continuam em série; no particionamento, os dados são divididos no início, e o step só termina quando a última partição termina (um &lt;code&gt;gridSize&lt;/code&gt; maior que o número de threads deixa os blocos menores e reduz essa espera). Com &lt;a href=&quot;https://kubernetes.io/docs/tasks/job/indexed-parallel-processing-static/&quot;&gt;Indexed Jobs&lt;/a&gt; no Kubernetes, o trabalho de cada índice também é fixado de antemão. Antes de otimizar, vale o conselho da própria documentação do Spring Batch: &lt;mark class=&quot;caneta-grifo&quot;&gt;muitos problemas se resolvem com um job de uma thread e um processo&lt;/mark&gt;, então meça primeiro.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sem custo de inicialização.&lt;/strong&gt; Os pods já estão rodando, com a JVM aquecida. A abordagem A sobe uma JVM a cada execução, o que é irrelevante para um job diário, mas pesa num job que roda a cada minuto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disparo sob demanda e fluxo contínuo.&lt;/strong&gt; Qualquer sistema pode disparar o processamento a qualquer momento, chamando o endpoint. E, se os itens chegam ao longo do dia como eventos, e não como uma lista fixa, a fila, aí com uma mensagem por item, é o modelo natural. Na abordagem A, o disparo fora de hora existe (&lt;code&gt;kubectl create job --from=cronjob/…&lt;/code&gt;), mas é operação, não integração.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Menos conceitos novos.&lt;/strong&gt; Não há Spring Batch para aprender nem tabelas de metadados para manter; em troca, entram DLQ, visibility timeout e redrive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;o-preço-da-abordagem-a&quot;&gt;O preço da abordagem A&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uma JVM por execução.&lt;/strong&gt; Alguns segundos de inicialização a cada rodada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idiossincrasias do CronJob.&lt;/strong&gt; Ele pode criar dois Jobs ou nenhum: a idempotência é obrigatória, e o alerta de “não rodou” também (critério 8).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O pod do job não é imortal.&lt;/strong&gt; Drenagem de nó, OOMKill e o próprio &lt;code&gt;activeDeadlineSeconds&lt;/code&gt; também o encerram. Se o processo morre sem atualizar o JobRepository, a execução fica como &lt;code&gt;STARTED&lt;/code&gt;, e toda nova tentativa com a mesma data, inclusive as do &lt;code&gt;backoffLimit&lt;/code&gt;, é recusada (&lt;code&gt;JobExecutionAlreadyRunningException&lt;/code&gt;) até alguém marcá-la como &lt;code&gt;FAILED&lt;/code&gt;. Num teste com Spring Boot 4.1.1, até um SIGTERM terminou assim: o Spring Boot fechou o pool de conexões com o step ainda rodando. Até o Spring Batch 5, destravar exigia um &lt;code&gt;UPDATE&lt;/code&gt; manual nas tabelas (&lt;a href=&quot;https://spring.io/blog/2021/01/27/spring-batch-on-kubernetes-efficient-batch-processing-at-scale&quot;&gt;Spring blog&lt;/a&gt;); no 6, existe &lt;span class=&quot;caneta caneta-caixa&quot;&gt;&lt;code&gt;JobOperator.&lt;wbr/&gt;recover(...)&lt;/code&gt;&lt;/span&gt;, mas alguém ainda precisa chamá-lo (&lt;a href=&quot;https://docs.spring.io/spring-batch/reference/job/advanced-meta-data.html#recover-job&quot;&gt;Spring Batch — Recovering a job&lt;/a&gt;). A execução do dia seguinte, com outra data, não é afetada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paralelismo definido antes da execução.&lt;/strong&gt; Se um dia o lote precisar de elasticidade, a fila oferece o caminho (dividir o lote em várias mensagens), e o pod do job, não.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Release acoplado.&lt;/strong&gt; Usar a mesma imagem significa que cada release da API leva junto uma nova versão do job, aplicada na próxima execução (desde que o pipeline atualize também a imagem do CronJob). Se os dois precisarem evoluir em ritmos diferentes, separe em módulos e imagens.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Curva de aprendizado e manutenção.&lt;/strong&gt; Mais um framework e as &lt;span class=&quot;caneta caneta-tendencia&quot;&gt;tabelas de metadados&lt;span class=&quot;caneta-tendencia-seta&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (aumenta)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, que crescem sem parar: o Spring Batch não tem equivalente ao &lt;code&gt;ttlSecondsAfterFinished&lt;/code&gt; do Job, e a limpeza fica por sua conta. O Spring Batch, porém, é opcional: um &lt;code&gt;ApplicationRunner&lt;/code&gt; com a coluna de status também funciona, sem o histórico por execução e a proteção do JobRepository.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;resumo&quot;&gt;Resumo&lt;/h2&gt;































































































&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Critério, A — CronJob, B — Endpoint + SQS&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Critério&lt;/th&gt;&lt;th&gt;A — CronJob&lt;/th&gt;&lt;th&gt;B — Endpoint + SQS&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Disputa de recursos com a API&lt;/td&gt;&lt;td&gt;Pod próprio&lt;/td&gt;&lt;td&gt;Mesmo processo&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Deploy durante o processamento&lt;/td&gt;&lt;td&gt;Não afeta o job&lt;/td&gt;&lt;td&gt;Interrompe o lote, que só volta depois do visibility timeout, em outra versão&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Recurso reservado&lt;/td&gt;&lt;td&gt;Só durante a execução&lt;/td&gt;&lt;td&gt;Folga para o pico do batch, o dia inteiro&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Autoscaling da API&lt;/td&gt;&lt;td&gt;Reage só ao tráfego&lt;/td&gt;&lt;td&gt;Reage também ao batch&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Destino fora do ar&lt;/td&gt;&lt;td&gt;Job falha; a próxima execução (ou um disparo manual) retoma&lt;/td&gt;&lt;td&gt;A mensagem volta à fila até cair na DLQ; retoma com redrive ou no próximo disparo&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Leitura da lista&lt;/td&gt;&lt;td&gt;No pod do job&lt;/td&gt;&lt;td&gt;No consumidor, dentro da API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Lote longo&lt;/td&gt;&lt;td&gt;Só o &lt;code&gt;activeDeadlineSeconds&lt;/code&gt; que você definir&lt;/td&gt;&lt;td&gt;O visibility timeout precisa cobri-lo (teto de 12 h)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Endpoint a proteger&lt;/td&gt;&lt;td&gt;Não existe&lt;/td&gt;&lt;td&gt;Existe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Visibilidade por execução&lt;/td&gt;&lt;td&gt;Pronta (Job + tabelas &lt;code&gt;BATCH_*&lt;/code&gt;, com o JobRepository no banco)&lt;/td&gt;&lt;td&gt;Precisa ser construída&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Resposta perdida na rede&lt;/td&gt;&lt;td&gt;Não acontece: a criação do Job já é idempotente&lt;/td&gt;&lt;td&gt;Segunda mensagem: dois pods no mesmo lote&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Duplicidade do CronJob&lt;/td&gt;&lt;td&gt;JobRepository (data de referência) + &lt;code&gt;Forbid&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Controle próprio (critério 9)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Retomar de onde parou&lt;/td&gt;&lt;td&gt;Coluna de status (&lt;em&gt;process indicator&lt;/em&gt;); pod morto exige &lt;code&gt;recover&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Coluna de status; a mensagem volta sozinha&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Falha isolada por item&lt;/td&gt;&lt;td&gt;Precisa configurar (skip, status)&lt;/td&gt;&lt;td&gt;Precisa programar (status); senão, a mensagem inteira volta&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Paralelismo&lt;/td&gt;&lt;td&gt;Definido antes da execução&lt;/td&gt;&lt;td&gt;Um pod só: a mensagem é uma&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Custo de inicialização&lt;/td&gt;&lt;td&gt;JVM a cada execução&lt;/td&gt;&lt;td&gt;Pods já rodando&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Disparo sob demanda&lt;/td&gt;&lt;td&gt;Manual (&lt;code&gt;kubectl create job --from&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;Natural&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Conceitos novos&lt;/td&gt;&lt;td&gt;Spring Batch (opcional)&lt;/td&gt;&lt;td&gt;Fila, DLQ, visibility timeout, redrive&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;como-montar-a-abordagem-a&quot;&gt;Como montar a abordagem A&lt;/h2&gt;
&lt;div class=&quot;caneta-carimbado&quot;&gt;&lt;p&gt;O que segue foi testado com Spring Boot 4.1.1 (Spring Batch 6.0.5), Java 21 e PostgreSQL 16, nos cenários que os critérios descrevem: execução normal, falha no meio do lote, nova execução no mesmo dia e no dia seguinte, duas execuções simultâneas, SIGKILL e SIGTERM no meio do processamento.&lt;/p&gt;&lt;p class=&quot;caneta-carimbo&quot;&gt;&lt;span class=&quot;caneta-carimbo-selo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt;Carimbo: &lt;/span&gt;testado no Spring Boot 4.1.1&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;&lt;strong&gt;A dependência.&lt;/strong&gt; No &lt;span class=&quot;marca-no-texto&quot;&gt;&lt;a class=&quot;marca-link&quot; href=&quot;https://spring.io/projects/spring-boot&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;Spring Boot&lt;/span&gt; 4, o &lt;code&gt;spring-boot-starter-batch&lt;/code&gt; sozinho usa o modo sem banco do Spring Batch 6 (&lt;code&gt;ResourcelessJobRepository&lt;/code&gt;): os metadados ficam em memória e somem quando o pod termina. Sem tabelas &lt;code&gt;BATCH_*&lt;/code&gt;, sem histórico de execuções e sem proteção contra uma segunda execução, ou seja, sem o que os critérios 8 a 10 descrevem. O JobRepository no banco vem do &lt;code&gt;spring-boot-starter-batch-jdbc&lt;/code&gt; (no Spring Boot 3, o &lt;code&gt;spring-boot-starter-batch&lt;/code&gt; já trazia o JDBC; ver o &lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Migration-Guide&quot;&gt;Spring Boot 4.0 Migration Guide&lt;/a&gt;):&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;pom.xml&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;XML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;xml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;org.springframework.boot&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;spring-boot-starter-batch-jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-visto&quot;&gt;&lt;p&gt;As tabelas precisam existir no banco. Por padrão (&lt;code&gt;spring.&lt;wbr/&gt;batch.&lt;wbr/&gt;jdbc.&lt;wbr/&gt;initialize-schema: embedded&lt;/code&gt;), o Spring Boot só cria o schema do Spring Batch em banco embutido; num PostgreSQL, a primeira execução falha com &lt;code&gt;relation &amp;quot;batch_job_instance&amp;quot; does not exist&lt;/code&gt;. No teste usei &lt;code&gt;initialize-schema: always&lt;/code&gt;; em produção, o caminho natural é aplicar por Flyway ou Liquibase o &lt;code&gt;schema-postgresql.&lt;wbr/&gt;sql&lt;/code&gt; que vem no &lt;code&gt;spring-batch-core&lt;/code&gt; (em &lt;code&gt;org/springframework/batch/core/&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Os perfis.&lt;/strong&gt; Uma imagem, dois perfis. Os beans de &lt;code&gt;Job&lt;/code&gt; e &lt;code&gt;Step&lt;/code&gt; ficam sob &lt;code&gt;@Profile(&amp;quot;batch&amp;quot;)&lt;/code&gt;. O &lt;code&gt;application.&lt;wbr/&gt;yml&lt;/code&gt; é a base de todos os perfis e desliga a execução automática de jobs, que é o que vale na API (ela roda sem perfil ativo). O &lt;code&gt;application-batch.&lt;wbr/&gt;yml&lt;/code&gt; só sobrescreve o que declara, por isso religa a execução explicitamente:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;application.yml (base, vale para todos os perfis)&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;YAML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;spring&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;job&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:12&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;application-batch.yml (perfil do job)&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;YAML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;spring&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;web-application-type&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;none&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;datasource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;hikari&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;maximum-pool-size&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# pool pequeno: o banco é compartilhado com a API&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;job&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;               &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# religa o que o application.yml desligou&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;enviarRegistrosJob&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;initialize-schema&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;always&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# ou migração por Flyway/Liquibase (ver acima)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Sem o &lt;code&gt;enabled: true&lt;/code&gt;, o pod no perfil &lt;code&gt;batch&lt;/code&gt; sobe, não executa job nenhum e sai com código 0, e o Kubernetes registra sucesso todo dia.&lt;/p&gt;&lt;/div&gt;
&lt;div class=&quot;caneta-margem caneta-asterisco&quot;&gt;&lt;p&gt;O &lt;code&gt;web-application-type: none&lt;/code&gt; tira só o servidor web. O resto do contexto sobe igual no pod do job: listeners de fila (&lt;code&gt;@SqsListener&lt;/code&gt;, &lt;code&gt;@KafkaListener&lt;/code&gt;), tarefas &lt;code&gt;@Scheduled&lt;/code&gt; e rotinas de aquecimento em &lt;code&gt;ApplicationRunner&lt;/code&gt; passam a trabalhar ali dentro, disputando CPU, memória e conexões com o lote. Coloque esses beans, e a classe com &lt;code&gt;@EnableScheduling&lt;/code&gt;, sob &lt;code&gt;@Profile(&amp;quot;!batch&amp;quot;)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;O exit code.&lt;/strong&gt; O &lt;code&gt;main&lt;/code&gt; propaga o exit code só no perfil &lt;code&gt;batch&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:10&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;App.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@SpringBootApplication&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;App&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ctx &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SpringApplication&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;App&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:2&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getEnvironment&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;acceptsProfiles&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Profiles&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;SpringApplication&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;propaga o exit code do job&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Com o Spring Batch, o Spring Boot registra um &lt;code&gt;ExitCodeGenerator&lt;/code&gt; que devolve código diferente de zero quando o job não termina &lt;code&gt;COMPLETED&lt;/code&gt;; no teste, um job &lt;code&gt;FAILED&lt;/code&gt; saiu com 5, a posição de &lt;code&gt;FAILED&lt;/code&gt; no enum &lt;code&gt;BatchStatus&lt;/code&gt; (&lt;a href=&quot;https://docs.spring.io/spring-boot/reference/features/spring-application.html#features.spring-application.application-exit&quot;&gt;Spring Boot — Application Exit&lt;/a&gt;). Sem o &lt;code&gt;System.&lt;wbr/&gt;exit&lt;/code&gt;, o processo sai com 0 mesmo quando o job falha, e o Kubernetes registra sucesso. Na API, sem o perfil &lt;code&gt;batch&lt;/code&gt;, o &lt;code&gt;main&lt;/code&gt; não chama &lt;code&gt;System.&lt;wbr/&gt;exit&lt;/code&gt;, e a aplicação continua no ar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A data de referência.&lt;/strong&gt; É ela que faz de cada dia uma instância própria no JobRepository e que permite recusar a execução duplicada dos critérios 9 e 10. O Kubernetes não calcula datas nos &lt;code&gt;args&lt;/code&gt; sem um shell, e, no Spring Batch 6, quando o job tem um incrementer, os parâmetros passados na linha de comando &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;são ignorados&lt;/span&gt; (fica só um aviso no log). Por isso quem gera a data é o incrementer do job, no mesmo fuso do &lt;code&gt;timeZone&lt;/code&gt; do CronJob:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:11&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;EnviarRegistrosJobConfig.java (trecho)&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Uma JobInstance por dia: a data de referência é o parâmetro identificador&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Job&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; enviarRegistrosJob&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JobRepository&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Step&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; enviarRegistrosStep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JobBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;enviarRegistrosJob&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:4&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;incrementer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;anteriores &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JobParametersBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addLocalDate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;dataReferencia&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;LocalDate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ZoneId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;America/Sao_Paulo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toJobParameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo abaixo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;a data de hoje, no fuso do CronJob&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;enviarRegistrosStep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O que aconteceu em cada caso, nos testes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;primeira execução do dia: &lt;code&gt;COMPLETED&lt;/code&gt;, exit code 0;&lt;/li&gt;
&lt;li&gt;nova execução no mesmo dia, depois de um &lt;code&gt;COMPLETED&lt;/code&gt;: recusada (&lt;code&gt;JobInstanceAlreadyCompleteException&lt;/code&gt;), exit code 1;&lt;/li&gt;
&lt;li&gt;nova execução no mesmo dia, depois de um &lt;code&gt;FAILED&lt;/code&gt;: restart da mesma instância, e o reader lê só os pendentes;&lt;/li&gt;
&lt;li&gt;no dia seguinte: uma instância nova.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Sem parâmetro nenhum, o job roda uma vez na vida: no Spring Batch 6, a instância de parâmetros vazios fica &lt;code&gt;COMPLETED&lt;/code&gt; no primeiro dia, e toda execução a partir do segundo é recusada. Com um &lt;code&gt;RunIdIncrementer&lt;/code&gt;, acontece o contrário: cada execução vira uma instância nova, e nada é recusado.&lt;/p&gt;&lt;/div&gt;
&lt;details&gt;&lt;summary&gt;Configuração completa do job (testada com Spring Boot 4.1.1 e Spring Batch 6.0.5)&lt;/summary&gt;&lt;p&gt;O SNS está simulado (o writer grava numa tabela &lt;code&gt;publicacao&lt;/code&gt; e registra no log); no serviço real, ali entra a chamada ao &lt;code&gt;SnsClient&lt;/code&gt;. Três detalhes do Spring Batch 6 aparecem no código: as interfaces de item mudaram de pacote (&lt;code&gt;org.&lt;wbr/&gt;springframework.&lt;wbr/&gt;batch.&lt;wbr/&gt;infrastructure.&lt;wbr/&gt;item&lt;/code&gt;); o step precisa de &lt;code&gt;.&lt;wbr/&gt;transactionManager(...)&lt;/code&gt;, senão usa um &lt;code&gt;ResourcelessTransactionManager&lt;/code&gt; e o JDBC do writer fica fora da transação do chunk; e o reader pagina por chave, com &lt;code&gt;saveState(false)&lt;/code&gt; (critério 11).&lt;/p&gt;&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:97&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;EnviarRegistrosJobConfig.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;br&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;exemplo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;LocalDate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ZoneId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;javax&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;slf4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Logger&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;slf4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;LoggerFactory&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;job&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Job&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;job&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JobBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;job&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;parameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JobParametersBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;repository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;step&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Step&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;step&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;StepBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;infrastructure&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ItemProcessor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;infrastructure&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ItemWriter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;infrastructure&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;database&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcPagingItemReader&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;infrastructure&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;database&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Order&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;infrastructure&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;database&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcPagingItemReaderBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Bean&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Configuration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;annotation&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;simple&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcClient&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;transaction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PlatformTransactionManager&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Configuration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Profile&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;batch&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;EnviarRegistrosJobConfig&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Logger&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; log &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LoggerFactory&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getLogger&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;EnviarRegistrosJobConfig&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; payload&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; status&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Uma JobInstance por dia: a data de referência é o parâmetro identificador&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Job&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; enviarRegistrosJob&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JobRepository&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Step&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; enviarRegistrosStep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JobBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;enviarRegistrosJob&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;incrementer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;anteriores &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; JobParametersBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;addLocalDate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;dataReferencia&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;LocalDate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ZoneId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;America/Sao_Paulo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toJobParameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;enviarRegistrosStep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Step&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; enviarRegistrosStep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JobRepository&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PlatformTransactionManager&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; transactionManager&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcPagingItemReader&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendentes&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcClient&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; StepBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;enviarRegistrosStep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jobRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Registro&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;chunk&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;transactionManager&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;transactionManager&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;reader&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pendentes&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;processor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;validar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;writer&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;publicarEMarcar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Process indicator: só os PENDENTE; sem estado salvo, o restart relê o que falta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bean&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcPagingItemReader&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendentes&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DataSource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcPagingItemReaderBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pendentes&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;selectClause&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;SELECT id, payload, status&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fromClause&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;FROM registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;whereClause&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;WHERE status = &amp;#39;PENDENTE&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sortKeys&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Order&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ASCENDING&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;dataRowMapper&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pageSize&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;saveState&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ItemProcessor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; validar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;payload&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;payload&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;payload&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;isBlank&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;INVALIDO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;ENVIADO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ItemWriter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; publicarEMarcar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;JdbcClient&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; chunk &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Registro&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; chunk&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;ENVIADO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// simula o SNS; no serviço real: snsClient.publish(...)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;INSERT INTO publicacao (registro_id, payload) VALUES (?, ?)&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;payload&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;info&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Publicado no SNS: registro {}&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;jdbc&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;UPDATE registro SET status = ? WHERE id = ?&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/details&gt;
&lt;p&gt;&lt;strong&gt;O CronJob.&lt;/strong&gt; Usa a mesma imagem da API. O que cada campo garante, e o que não garante, está no post &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/kubernetes-cronjob-concorrencia/&quot;&gt;Kubernetes CronJob — concorrência, retries e tempo máximo de execução&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:31&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;cronjob.yaml&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;YAML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;batch/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;CronJob&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;enviar-registros&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;schedule&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;0 3 * * *&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;timeZone&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;America/Sao_Paulo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:1&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrencyPolicy&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Forbid&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;um Job por vez, nunca dois&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;startingDeadlineSeconds&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3600&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# atrasou mais de 1 h: pula e espera o próximo dia&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;successfulJobsHistoryLimit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;failedJobsHistoryLimit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jobTemplate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;backoffLimit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;activeDeadlineSeconds&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;7200&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# com Forbid, um Job travado bloquearia os próximos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;restartPolicy&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Never&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;containers&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;worker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;meu-servico:1.2.3&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# a mesma imagem do Deployment da API&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;SPRING_PROFILES_ACTIVE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;batch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;resources&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;requests&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;500m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;1Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;limits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;1Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul class=&quot;caneta-lista caneta-caixas&quot;&gt;
&lt;li&gt;&lt;code class=&quot;caneta caneta-caixa caneta-caixa-codigo&quot;&gt;timeZone&lt;/code&gt;: sem ele, o horário é lido no fuso do kube-controller-manager, em geral UTC, e as 03:00 viram meia-noite em Brasília, bem na virada da data que o incrementer calcula.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;caneta caneta-caixa caneta-caixa-codigo&quot;&gt;activeDeadlineSeconds&lt;/code&gt;: com &lt;code&gt;Forbid&lt;/code&gt;, um Job travado faria o CronJob pular todas as execuções seguintes; o prazo derruba o Job e libera a agenda (e, como visto em “O preço da abordagem A”, a execução interrompida fica &lt;code&gt;STARTED&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;caneta caneta-caixa caneta-caixa-codigo&quot;&gt;startingDeadlineSeconds&lt;/code&gt;: se o Job não for criado até uma hora depois do horário, a execução é pulada, e os pendentes ficam para o dia seguinte.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;caneta caneta-caixa caneta-caixa-codigo&quot;&gt;resources&lt;/code&gt;: os valores do exemplo do critério 3. Sem eles, o pod fica na classe &lt;code&gt;BestEffort&lt;/code&gt;: não reserva nada no nó e é o primeiro a ser despejado. Com &lt;code&gt;limits.&lt;wbr/&gt;memory: 1Gi&lt;/code&gt;, a JVM usa por padrão só 25% disso para o heap; se a imagem não ajusta o heap, defina &lt;code&gt;-XX:MaxRAMPercentage&lt;/code&gt; (&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html&quot;&gt;The java Command&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Se o CronJob sair do mesmo template do Deployment (Helm, Kustomize), deixe de fora as probes de liveness e de startup: sem servidor web, ninguém responde ao &lt;code&gt;/actuator/health&lt;/code&gt;, o kubelet mata o container no meio do job, e cada nova tentativa do &lt;code&gt;backoffLimit&lt;/code&gt; falha do mesmo jeito.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Referências para essa configuração: &lt;a href=&quot;https://docs.spring.io/spring-boot/reference/io/spring-batch.html&quot;&gt;Spring Boot — Spring Batch&lt;/a&gt; (execução do job na inicialização e as propriedades &lt;code&gt;spring.&lt;wbr/&gt;batch.*&lt;/code&gt;), &lt;a href=&quot;https://docs.spring.io/spring-boot/reference/features/spring-application.html#features.spring-application.application-exit&quot;&gt;Spring Boot — Application Exit&lt;/a&gt; e &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/&quot;&gt;Kubernetes — CronJob&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;Para uma lista fixa no banco, processada em horário agendado e com trabalho leve por item, &lt;mark class=&quot;caneta-marca&quot;&gt;a abordagem A vence nos critérios que mais pesam&lt;/mark&gt;: isolamento de recursos, deploy da API sem interromper o job, recurso reservado só quando necessário, um gatilho que já nasce idempotente, nenhum lote preso ao prazo de uma mensagem e menos peças para operar. E a visibilidade por execução já vem pronta. Isso vale desde que ela seja montada com os cuidados da seção anterior: JobRepository no banco, data de referência como parâmetro identificador e um CronJob com fuso, prazos e recursos definidos.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-visto&quot;&gt;&lt;p&gt;A abordagem B passa à frente quando os itens chegam continuamente como eventos, quando o processamento por item é pesado ou variável, ou quando o volume pede elasticidade. Mas aí o desenho também muda: em vez de uma mensagem por execução, uma por item, ou por faixa de itens, consumidas num Deployment próprio, no estilo &lt;a href=&quot;https://learn.microsoft.com/azure/architecture/guide/architecture-styles/web-queue-worker&quot;&gt;Web-Queue-Worker&lt;/a&gt;, e não dentro da API, onde os problemas dos critérios 1 a 4 continuam existindo. De preferência, escale esse Deployment pela profundidade da fila, inclusive até zero: parado o dia inteiro, ele volta ao problema do critério 3. E o gatilho nem precisa ser HTTP: o próprio CronJob da abordagem A pode ler a lista e enfileirar. Some o endpoint (critério 7), e a duplicidade do critério 9 só muda de lugar, para o produtor, que precisa marcar o que já enfileirou.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;No cenário deste post, a fila consumida dentro da API também resolve. Mas, para chegar ao mesmo lugar, você constrói e opera mais peças, reserva recurso na API o dia inteiro, amarra o lote ao prazo de uma mensagem e mantém o processamento disputando espaço com quem atende o usuário.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Michael T. Nygard — &lt;a href=&quot;https://pragprog.com/titles/mnee2/release-it-second-edition/&quot;&gt;&lt;em&gt;Release It! Design and Deploy Production-Ready Software&lt;/em&gt;, 2ª ed.&lt;/a&gt; (Pragmatic Bookshelf; padrão Bulkhead)&lt;/li&gt;
&lt;li&gt;Martin Kleppmann — &lt;a href=&quot;https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/ch10.html&quot;&gt;&lt;em&gt;Designing Data-Intensive Applications&lt;/em&gt;, 1ª ed., cap. 10 (Batch Processing)&lt;/a&gt; (O’Reilly, 2017); na &lt;a href=&quot;https://www.oreilly.com/library/view/designing-data-intensive-applications/9781098119058/ch11.html&quot;&gt;2ª ed.&lt;/a&gt;, com Chris Riccomini, o tema está no cap. 11&lt;/li&gt;
&lt;li&gt;Verma et al. — &lt;a href=&quot;https://research.google/pubs/large-scale-cluster-management-at-google-with-borg/&quot;&gt;Large-scale cluster management at Google with Borg&lt;/a&gt; (EuroSys 2015)&lt;/li&gt;
&lt;li&gt;The Twelve-Factor App — &lt;a href=&quot;https://12factor.net/concurrency&quot;&gt;VIII. Concurrency&lt;/a&gt; e &lt;a href=&quot;https://12factor.net/disposability&quot;&gt;IX. Disposability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microsoft — &lt;a href=&quot;https://learn.microsoft.com/azure/architecture/patterns/bulkhead&quot;&gt;Bulkhead pattern&lt;/a&gt;, &lt;a href=&quot;https://learn.microsoft.com/azure/architecture/guide/architecture-styles/web-queue-worker&quot;&gt;Web-Queue-Worker architecture style&lt;/a&gt; e &lt;a href=&quot;https://learn.microsoft.com/azure/architecture/best-practices/background-jobs&quot;&gt;Best practices for background jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Amazon Builders’ Library — &lt;a href=&quot;https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/&quot;&gt;Timeouts, retries, and backoff with jitter&lt;/a&gt; e &lt;a href=&quot;https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/&quot;&gt;Making retries safe with idempotent APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Chris Jones — &lt;a href=&quot;https://thenewstack.io/rethinking-java-scheduled-tasks-in-kubernetes/&quot;&gt;Rethinking Java @Scheduled Tasks in Kubernetes&lt;/a&gt; (The New Stack, 2023)&lt;/li&gt;
&lt;li&gt;Chris Jones — &lt;a href=&quot;https://aws.amazon.com/blogs/opensource/alternative-jar-entry-points-using-a-dependency-injection-framework-for-existing-java-applications/&quot;&gt;Alternative JAR Entry Points Using Java Dependency Injection Frameworks&lt;/a&gt; (AWS Open Source Blog) e &lt;a href=&quot;https://github.com/aws-samples/multiple-entry-points-with-dependency-injection&quot;&gt;código de exemplo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Mahmoud Ben Hassine — &lt;a href=&quot;https://spring.io/blog/2021/01/27/spring-batch-on-kubernetes-efficient-batch-processing-at-scale&quot;&gt;Spring Batch on Kubernetes: Efficient batch processing at scale&lt;/a&gt; (Spring blog, 2021)&lt;/li&gt;
&lt;li&gt;Rohit Raveendran — &lt;a href=&quot;https://www.cncf.io/blog/2024/12/19/decoding-the-pod-termination-lifecycle-in-kubernetes-a-comprehensive-guide/&quot;&gt;Decoding the pod termination lifecycle in Kubernetes: a comprehensive guide&lt;/a&gt; (blog da CNCF, 2024)&lt;/li&gt;
&lt;li&gt;Kubernetes — &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/&quot;&gt;CronJob&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/job/&quot;&gt;Jobs&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination&quot;&gt;término de pods&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-resize&quot;&gt;Resizing Pods&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/&quot;&gt;requests e limits&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/&quot;&gt;Horizontal Pod Autoscaling&lt;/a&gt;, &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/autoscaling/vertical-pod-autoscale/&quot;&gt;Vertical Pod Autoscaling&lt;/a&gt; e &lt;a href=&quot;https://kubernetes.io/docs/tasks/job/indexed-parallel-processing-static/&quot;&gt;Indexed Jobs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kubernetes — &lt;a href=&quot;https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/cronjob/utils.go&quot;&gt;código do controlador de CronJob&lt;/a&gt; (nome do Job derivado do horário agendado)&lt;/li&gt;
&lt;li&gt;kube-state-metrics — &lt;a href=&quot;https://github.com/kubernetes/kube-state-metrics/blob/main/docs/metrics/workload/job-metrics.md&quot;&gt;métricas de Job&lt;/a&gt; e &lt;a href=&quot;https://github.com/kubernetes/kube-state-metrics/blob/main/docs/metrics/workload/cronjob-metrics.md&quot;&gt;métricas de CronJob&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Boot — &lt;a href=&quot;https://docs.spring.io/spring-boot/reference/features/profiles.html&quot;&gt;Profiles&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-boot/reference/io/spring-batch.html&quot;&gt;Spring Batch&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-boot/reference/features/spring-application.html#features.spring-application.application-exit&quot;&gt;Application Exit&lt;/a&gt; e &lt;a href=&quot;https://docs.spring.io/spring-boot/reference/web/graceful-shutdown.html&quot;&gt;Graceful Shutdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Boot — &lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Migration-Guide&quot;&gt;Spring Boot 4.0 Migration Guide&lt;/a&gt; (Spring Batch sem banco por padrão e o &lt;code&gt;spring-boot-starter-batch-jdbc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Spring Batch — &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/whatsnew.html&quot;&gt;What’s new in Spring Batch 6&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/job/configuring-repository.html&quot;&gt;Configuring a JobRepository&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/job/advanced-meta-data.html&quot;&gt;Advanced Meta-Data Usage&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/schema-appendix.html&quot;&gt;Meta-Data Schema&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/readers-and-writers/process-indicator.html&quot;&gt;Preventing State Persistence&lt;/a&gt;, &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/readers-and-writers/database.html&quot;&gt;Database&lt;/a&gt; e &lt;a href=&quot;https://docs.spring.io/spring-batch/reference/scalability.html&quot;&gt;Scaling and Parallel Processing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Cloud AWS — &lt;a href=&quot;https://github.com/awspring/spring-cloud-aws/blob/v4.1.1/docs/src/main/asciidoc/sqs.adoc&quot;&gt;SQS&lt;/a&gt; (visibilidade da mensagem, &lt;code&gt;listenerShutdownTimeout&lt;/code&gt; e &lt;code&gt;ExponentialBackoffErrorHandler&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Amazon SQS — &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html&quot;&gt;Standard queues&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html&quot;&gt;Visibility timeout&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html&quot;&gt;Dead-letter queues&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-dead-letter-queue-redrive.html&quot;&gt;DLQ redrive&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues-exactly-once-processing.html&quot;&gt;Exactly-once processing (FIFO)&lt;/a&gt; e &lt;a href=&quot;https://aws.amazon.com/sqs/pricing/&quot;&gt;Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Amazon SNS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/api/API_PublishBatch.html&quot;&gt;PublishBatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;HikariCP — &lt;a href=&quot;https://github.com/brettwooldridge/HikariCP&quot;&gt;README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;KEDA — &lt;a href=&quot;https://keda.sh/docs/2.20/scalers/aws-sqs/&quot;&gt;AWS SQS Queue scaler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ShedLock — &lt;a href=&quot;https://github.com/lukas-krecan/ShedLock&quot;&gt;README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Oracle — &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html&quot;&gt;The java Command&lt;/a&gt; (&lt;code&gt;-XX:MaxRAMPercentage&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Arquitetura de Software</category><category>Kubernetes</category><category>Spring</category><category>Mensageria</category><category>Trade-offs</category></item><item><title>Java 29 (próxima LTS) — o que o Java 26 e o 27 já trouxeram</title><link>https://blog.cesarschutz.com.br/posts/java-29/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/java-29/</guid><description>O caminho do Java 25 até a próxima LTS, o Java 29 (prevista para setembro de 2027): as JEPs do Java 26 e do 27, o que ainda está em preview, exemplos de código e o que conferir na migração.</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Última atualização:&lt;/strong&gt; 16/09/2026. Cobre o Java 26 (lançado em 17/03/2026) e o Java 27 (lançado em 15/09/2026). O Java 28 ainda está em desenvolvimento, e o conteúdo do Java 29 ainda não foi definido.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A série “Atualizações do Java” acompanha só as versões LTS. Entre uma LTS e outra saem versões intermediárias a cada seis meses, e cada uma pode trazer recursos novos, promover um preview a final ou remover algo antigo. Este post junta o que já saiu desde o Java 25 e diz &lt;strong&gt;em qual versão cada coisa chegou&lt;/strong&gt; e em qual status ela está hoje. Ele será atualizado quando o Java 28 e o Java 29 saírem.&lt;/p&gt;
&lt;p&gt;O Java 26 chegou à disponibilidade geral (GA, a versão final para produção) em 17 de março de 2026 (&lt;a href=&quot;https://openjdk.org/projects/jdk/26/&quot;&gt;JDK 26&lt;/a&gt;), e o Java 27, em 15 de setembro de 2026 (&lt;a href=&quot;https://openjdk.org/projects/jdk/27/&quot;&gt;JDK 27&lt;/a&gt;). A próxima LTS prevista é o &lt;strong&gt;Java 29, em setembro de 2027&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Essa previsão vem do &lt;a href=&quot;https://www.oracle.com/java/technologies/java-se-support-roadmap.html&quot;&gt;Oracle Java SE Support Roadmap&lt;/a&gt; (atualizado em 15/09/2026). Ele classifica o 26, o 27 e o 28 como não LTS e avisa que essa classificação e as datas ainda podem mudar. Nesse roadmap, cada versão não LTS tem Premier Support só até a seguinte sair: setembro de 2026 para o 26 e março de 2027 para o 27. Para o Java 25, a Oracle informa Premier Support até setembro de 2030; para o Java 29, prevê até setembro de 2032. Outros fornecedores de builds do OpenJDK publicam seus próprios prazos. Na data desta atualização, o OpenJDK ainda não tinha publicado a página do projeto JDK 29.&lt;/p&gt;
&lt;p&gt;O post é para quem está no &lt;strong&gt;Java 25&lt;/strong&gt; e quer acompanhar o que muda até o 29. O ponto de partida é o &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/&quot;&gt;post do Java 25&lt;/a&gt;; quem vem do Java 21 deve ler os dois. Para a visão geral de ciclo de releases, distribuições e estratégia de migração, veja o &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/guia-atualizacoes-java/&quot;&gt;guia de atualizações do Java&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Como o post está organizado.&lt;/strong&gt; Primeiro, uma linha do tempo com todas as trilhas. Depois, os recursos que já são definitivos, agrupados por tema: concorrência, APIs, JVM, ferramentas, segurança e remoções. Em seguida vêm os recursos que continuam em preview ou incubadora, uma lista do que pode quebrar na migração vindo do Java 25 e, por fim, a tabela de todas as JEPs de cada versão, incluindo o que já tem alvo no Java 28. Cada recurso traz a linha &lt;strong&gt;Chegou em&lt;/strong&gt;, com a versão e a JEP (a proposta formal de mudança do OpenJDK) em que ele apareceu.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Preview e incubadora não são definitivos.&lt;/strong&gt; Pela &lt;a href=&quot;https://openjdk.org/jeps/12&quot;&gt;JEP 12&lt;/a&gt;, um recurso em &lt;strong&gt;preview&lt;/strong&gt; está completo, mas não é permanente: numa versão futura ele pode virar final, com ou sem ajustes, ou ser removido. Para usá-lo é preciso &lt;code&gt;--enable-preview&lt;/code&gt; na compilação e na execução, e uma JVM não carrega classes compiladas com os previews de outra versão. Já as APIs em &lt;strong&gt;incubadora&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/jeps/11&quot;&gt;JEP 11&lt;/a&gt;) ficam em módulos &lt;code&gt;jdk.&lt;wbr&gt;incubator.*&lt;/code&gt;, precisam de &lt;code&gt;--add-modules&lt;/code&gt; e podem mudar ou sumir com a mesma liberdade. Os exemplos de preview abaixo refletem o Java 27 e podem precisar de ajuste no Java 28 ou no 29.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Os exemplos que só dependem do Java 26 foram compilados e executados no Temurin 26.0.2. Os que usam recursos exclusivos do 27 (&lt;code&gt;Set.&lt;wbr&gt;ofLazy&lt;/code&gt;, o &lt;code&gt;StructuredTaskScope&lt;/code&gt; do 27, o mascaramento de dados do JFR e &lt;code&gt;-XX:AOTMode=required&lt;/code&gt;) seguem as assinaturas do código-fonte do JDK 27 (tag &lt;code&gt;jdk-27-ga&lt;/code&gt;) e as notas de release.&lt;/p&gt;
&lt;h2 id=&quot;linha-do-tempo&quot;&gt;Linha do tempo&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/java-29/linha-do-tempo.svg&quot; alt=&quot;Linha do tempo do Java 25 ao Java 29: trilhas de Lazy Constants, Structured Concurrency, primitivos em patterns, API PEM e Vector API passando por previews e incubadoras; compact object headers e G1 virando padrão no Java 27; outras JEPs de cada versão e o que já é alvo do Java 28&quot;&gt;&lt;/p&gt;
&lt;p&gt;O diagrama mostra cada trilha versão a versão. A linha vermelha marca a data desta atualização: à direita dela, tudo é previsão.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java 26&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/projects/jdk/26/&quot;&gt;página do projeto&lt;/a&gt;), 10 JEPs: HTTP/3 no &lt;code&gt;HttpClient&lt;/code&gt;, cache AOT com qualquer coletor, G1 com menos sincronização, avisos para quem altera campos &lt;code&gt;final&lt;/code&gt; por reflexão e a remoção da Applet API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java 27&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/projects/jdk/27/&quot;&gt;página do projeto&lt;/a&gt;), 9 JEPs: G1 como padrão em qualquer ambiente, compact object headers por padrão, TLS 1.3 com troca de chaves pós-quântica e mascaramento de dados sensíveis nas gravações do JFR.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java 28&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/projects/jdk/28/&quot;&gt;página do projeto&lt;/a&gt;), 6 JEPs com alvo até agora, entre elas a API PEM final e o primeiro preview de Value Objects (&lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#java-28&quot;&gt;detalhes&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Os recursos em preview e incubadora (Structured Concurrency, primitivos em patterns, Lazy Constants, API PEM e Vector API) estão reunidos em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#ainda-em-preview-ou-incubadora&quot;&gt;Ainda em preview ou incubadora&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;concorrência&quot;&gt;Concorrência&lt;/h2&gt;
&lt;h3 id=&quot;virtual-threads-liberam-a-carrier-enquanto-esperam-a-inicialização-de-uma-classe&quot;&gt;Virtual threads liberam a carrier enquanto esperam a inicialização de uma classe&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 26 (final, &lt;a href=&quot;https://bugs.openjdk.org/browse/JDK-8369238&quot;&gt;JDK-8369238&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Uma virtual thread não tem thread do sistema operacional própria: ela é executada em cima de uma &lt;strong&gt;carrier thread&lt;/strong&gt;, uma thread de plataforma de um pool compartilhado pela JVM. Quando a virtual thread bloqueia, a JVM a “desmonta” da carrier, que fica livre para executar outra virtual thread. Se ela não pode ser desmontada, fica &lt;strong&gt;presa (pinned)&lt;/strong&gt; e ocupa a carrier durante toda a espera. O Java 24 resolveu esse problema para &lt;code&gt;synchronized&lt;/code&gt; (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#synchronized-n%C3%A3o-prende-mais-virtual-threads&quot;&gt;&lt;code&gt;synchronized&lt;/code&gt; não prende mais virtual threads&lt;/a&gt;, no post do Java 25), mas ainda havia outros casos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Até o Java 25, uma virtual thread que precisava de uma classe que outra thread ainda estava inicializando (rodando o bloco &lt;code&gt;static&lt;/code&gt;, por exemplo) ficava presa à carrier enquanto esperava. No pior caso, todas as carriers ficavam presas nessa espera enquanto o inicializador dependia de uma virtual thread para terminar, e a aplicação inteira travava.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; Segundo as &lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas de release do Java 26&lt;/a&gt;, na maioria dos casos a virtual thread agora é desmontada durante essa espera e libera a carrier. A mudança não é uma JEP e não exige nenhuma alteração no código: basta rodar no Java 26 ou posterior.&lt;/p&gt;
&lt;h2 id=&quot;apis-da-biblioteca-padrão&quot;&gt;APIs da biblioteca padrão&lt;/h2&gt;
&lt;h3 id=&quot;http3-no-httpclient&quot;&gt;HTTP/3 no HttpClient&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 26 (final, &lt;a href=&quot;https://openjdk.org/jeps/517&quot;&gt;JEP 517&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; O &lt;code&gt;java.&lt;wbr&gt;net.&lt;wbr&gt;http.&lt;wbr&gt;HttpClient&lt;/code&gt; (&lt;a href=&quot;https://openjdk.org/jeps/321&quot;&gt;JEP 321&lt;/a&gt;, Java 11, &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-11/#http-client&quot;&gt;HTTP Client no post do Java 11&lt;/a&gt;) falava HTTP/1.1 e HTTP/2. O HTTP/3, padronizado pela IETF em 2022, troca o TCP pelo QUIC, um protocolo de transporte que roda sobre UDP. A JEP cita as vantagens: handshakes (a negociação inicial da conexão) potencialmente mais rápidos, menos problemas de congestionamento, como o head-of-line blocking (quando um pacote perdido atrasa todas as requisições da conexão), e transporte mais confiável em redes que perdem muitos pacotes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; O HTTP/3 é &lt;strong&gt;opt-in&lt;/strong&gt;: o padrão continua sendo HTTP/2. Você escolhe &lt;code&gt;HttpClient.&lt;wbr&gt;Version.&lt;wbr&gt;HTTP_3&lt;/code&gt; no cliente ou em cada requisição. Por padrão, se o servidor não fala HTTP/3, o cliente volta para HTTP/2 ou HTTP/1.1 sem erro (a exceção é o modo &lt;code&gt;HTTP_3_URI_ONLY&lt;/code&gt;, na tabela abaixo). Como não dá para saber de antemão se o servidor fala HTTP/3, a JEP descreve quatro estratégias de descoberta:&lt;/p&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Configuração, Comportamento&quot;&gt;
























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Configuração&lt;/th&gt;&lt;th&gt;Comportamento&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;HTTP_3&lt;/code&gt; como versão preferida da requisição&lt;/td&gt;&lt;td&gt;Tenta HTTP/3 primeiro e cai para HTTP/2 ou HTTP/1.1 se a conexão não abrir em tempo razoável.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;HTTP_3&lt;/code&gt; só no cliente, sem versão na requisição&lt;/td&gt;&lt;td&gt;Tenta HTTP/3 e HTTP/2 ou HTTP/1.1 em paralelo e usa a conexão que abrir primeiro.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;HttpOption.&lt;wbr&gt;H3_DISCOVERY&lt;/code&gt; com &lt;code&gt;Http3DiscoveryMode.&lt;wbr&gt;ALT_SVC&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Começa em HTTP/2 ou HTTP/1.1 e passa a usar HTTP/3 nas requisições seguintes se o servidor anunciar o serviço alternativo.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;HttpOption.&lt;wbr&gt;H3_DISCOVERY&lt;/code&gt; com &lt;code&gt;Http3DiscoveryMode.&lt;wbr&gt;HTTP_3_URI_ONLY&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Usa só HTTP/3 e falha se o servidor não responder por ele.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;As duas últimas estratégias usam a opção de requisição &lt;code&gt;H3_DISCOVERY&lt;/code&gt; e exigem &lt;code&gt;HTTP_3&lt;/code&gt; como versão preferida no cliente ou na requisição.&lt;/p&gt;
&lt;p&gt;O exemplo abaixo usa a terceira estratégia (&lt;code&gt;ALT_SVC&lt;/code&gt;). Ele acessa um servidor externo, &lt;code&gt;www.&lt;wbr&gt;google.&lt;wbr&gt;com&lt;/code&gt;, e só chega ao HTTP/3 porque esse servidor anuncia suporte no cabeçalho &lt;code&gt;Alt-Svc&lt;/code&gt; da resposta. Com um servidor que não anuncia HTTP/3, as duas chamadas saem em &lt;code&gt;HTTP_2&lt;/code&gt;; sem acesso à internet, &lt;code&gt;send&lt;/code&gt; lança exceção.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:29&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ClienteHttp3.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;URI&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpClient&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpOption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpOption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Http3DiscoveryMode&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpRequest&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpResponse&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BodyHandlers&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;ClienteHttp3&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Preferência por HTTP/3 em todas as requisições deste cliente&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpClient&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; client &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; HttpClient&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;newBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;HttpClient&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;HTTP_3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Servidor externo: o resultado depende de ele anunciar HTTP/3 (Alt-Svc)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;HttpRequest&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; request &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; HttpRequest&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;newBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;URI&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;https://www.google.com/&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setOption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;HttpOption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;H3_DISCOVERY&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Http3DiscoveryMode&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ALT_SVC&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 1ª chamada: sai por HTTP/2 e lê o Alt-Svc da resposta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; primeira &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; client&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;send&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; BodyHandlers&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;discarding&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;primeira&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// HTTP_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 2ª chamada: já usa HTTP/3, se o servidor anunciou&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; segunda &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; client&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;send&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; BodyHandlers&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;discarding&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;segunda&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// HTTP_3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No Temurin 26.0.2, com acesso à internet em 16/09/2026, esse programa imprimiu &lt;code&gt;HTTP_2&lt;/code&gt; e depois &lt;code&gt;HTTP_3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quando usar e cuidados.&lt;/strong&gt; Vale testar o HTTP/3 com servidores e CDNs que já o oferecem, principalmente em redes com perda de pacotes. Limitações da primeira versão, segundo a JEP: só funciona com o provider TLS padrão (SunJSSE), não há API pública de QUIC nem servidor HTTP/3, e o &lt;code&gt;java.&lt;wbr&gt;net.&lt;wbr&gt;URL&lt;/code&gt; continua só em HTTP/1.1.&lt;/p&gt;
&lt;h3 id=&quot;apis-menores-sem-jep&quot;&gt;APIs menores sem JEP&lt;/h3&gt;
&lt;p&gt;Nem toda mudança de API passa por uma JEP. As notas de release registram várias adições pequenas e úteis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Java 26&lt;/strong&gt; (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas de release&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Process&lt;/code&gt; implementa &lt;code&gt;AutoCloseable&lt;/code&gt; (e &lt;code&gt;Closeable&lt;/code&gt;): fechar o processo garante que ele terminou e libera streams e recursos, então dá para usá-lo em &lt;code&gt;try&lt;/code&gt;-with-resources.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Comparator&lt;/code&gt; ganhou os métodos default &lt;code&gt;min(T, T)&lt;/code&gt; e &lt;code&gt;max(T, T)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UUID.&lt;wbr&gt;ofEpochMillis(long)&lt;/code&gt; cria UUIDs versão 7, que começam pelo timestamp, em milissegundos, e por isso ficam ordenados pelo instante de criação.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Instant.&lt;wbr&gt;plusSaturating(Duration)&lt;/code&gt; soma sem estourar: no limite, devolve &lt;code&gt;Instant.&lt;wbr&gt;MIN&lt;/code&gt; ou &lt;code&gt;Instant.&lt;wbr&gt;MAX&lt;/code&gt;. &lt;code&gt;Duration&lt;/code&gt; ganhou as constantes &lt;code&gt;MIN&lt;/code&gt; e &lt;code&gt;MAX&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HttpRequest.&lt;wbr&gt;BodyPublishers.&lt;wbr&gt;ofFileChannel(channel, offset, length)&lt;/code&gt; envia só um trecho de um arquivo, útil para upload em partes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;java.&lt;wbr&gt;nio.&lt;wbr&gt;ByteOrder&lt;/code&gt; virou &lt;code&gt;enum&lt;/code&gt; e pode ser usado em &lt;code&gt;switch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Suporte a Unicode 17.0 e ao JDBC 4.5 MR, que inclui os tipos SQL &lt;code&gt;DECFLOAT&lt;/code&gt; e &lt;code&gt;JSON&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:27&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ApisMenores.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Comparator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UUID&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;ApisMenores&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Process agora é AutoCloseable: processo e streams são liberados ao sair do bloco&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// (a saída de &quot;java -version&quot; vai para o stream do processo, não aparece aqui)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Process&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ProcessBuilder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;-version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;waitFor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Comparator ganhou min/max entre dois valores&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Comparator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; porTamanho &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Comparator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;comparingInt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;porTamanho&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;max&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;kotlin&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// kotlin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// UUID versão 7, ordenável pelo instante de criação&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UUID&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; UUID&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofEpochMillis&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentTimeMillis&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 7&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Soma saturada: em vez de estourar, para no limite&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;MAX&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;minusSeconds&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;plusSaturating&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofDays&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;MAX&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;MAX&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// PT2562047788015215H30M7.999999999S&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Java 27&lt;/strong&gt; (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas de release&lt;/a&gt;): &lt;code&gt;KeyStore.&lt;wbr&gt;getCreationInstant&lt;/code&gt; devolve a data de criação de uma entrada como &lt;code&gt;Instant&lt;/code&gt;; na Foreign Function &amp;#x26; Memory API, &lt;code&gt;Linker.&lt;wbr&gt;Option.&lt;wbr&gt;captureCallState&lt;/code&gt; também inicializa o estado thread-local antes da downcall (a chamada de Java para uma função nativa); e os formatadores ISO predefinidos de &lt;code&gt;DateTimeFormatter&lt;/code&gt; passam a aceitar offsets curtos, como &lt;code&gt;+01&lt;/code&gt;, no parsing.&lt;/p&gt;
&lt;h2 id=&quot;jvm-gc-e-desempenho&quot;&gt;JVM, GC e desempenho&lt;/h2&gt;
&lt;h3 id=&quot;g1-com-menos-sincronização-entre-aplicação-e-gc&quot;&gt;G1 com menos sincronização entre aplicação e GC&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 26 (final, &lt;a href=&quot;https://openjdk.org/jeps/522&quot;&gt;JEP 522&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;O G1 divide o heap em regiões e, para não varrer o heap inteiro a cada coleta, anota numa &lt;strong&gt;card table&lt;/strong&gt; quais trechos da memória guardam referências para objetos de outras regiões. Quem mantém essa tabela são as &lt;strong&gt;write barriers&lt;/strong&gt;: pequenos trechos de código que a JVM injeta na aplicação e que rodam a cada atribuição de referência, como &lt;code&gt;pedido.&lt;wbr&gt;cliente = c&lt;/code&gt;. Em segundo plano, threads de otimização do G1 processam a mesma tabela.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Até o Java 25, a aplicação e as threads de otimização mexiam na mesma card table e precisavam se sincronizar. Essa sincronização deixava as write barriers longas e lentas, e elas rodam o tempo todo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; A JEP 522 cria uma &lt;strong&gt;segunda card table&lt;/strong&gt;. A aplicação escreve numa tabela sem sincronizar, as threads de otimização trabalham na outra, e o G1 troca as duas de forma atômica quando precisa.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/java-29/g1-duas-card-tables.svg&quot; alt=&quot;Comparação entre o G1 até o Java 25, com aplicação e threads de otimização disputando uma única card table sincronizada, e o G1 do Java 26, com duas card tables: a aplicação escreve numa, as threads de otimização processam a outra e o G1 troca as duas de forma atômica&quot;&gt;&lt;/p&gt;
&lt;p&gt;No diagrama, à esquerda está o modelo antigo, com uma tabela disputada pelos dois lados; à direita, o novo, em que cada lado tem a sua tabela e as setas laranja indicam a troca.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resultado e custo.&lt;/strong&gt; A JEP relata ganhos de throughput (trabalho feito por unidade de tempo) de 5% a 15% em aplicações que modificam muitos campos de referência, e de até 5% nas demais. No x64, as write barriers caíram de cerca de 50 instruções para 12. O custo é memória nativa: cada card table ocupa 0,2% da capacidade do heap, ou cerca de 2 MB por GB. Não há flag nova: basta usar o G1 no Java 26 ou posterior.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/java-29/jvm-padroes-java-27.svg&quot; alt=&quot;Dois padrões da JVM que mudam no Java 27: sem flag explícita, o coletor passa a ser sempre G1 (antes era Serial em máquinas com 1 CPU ou menos de 1792 MB), e o cabeçalho de objeto passa de 96 para 64 bits&quot;&gt;&lt;/p&gt;
&lt;p&gt;O Java 27 muda dois padrões da JVM, resumidos no diagrama e detalhados nas duas seções seguintes: o coletor escolhido quando nenhum é informado e o tamanho do cabeçalho dos objetos. Os dois só afetam quem não passa a flag correspondente na linha de comando.&lt;/p&gt;
&lt;h3 id=&quot;g1-como-coletor-padrão-em-qualquer-ambiente&quot;&gt;G1 como coletor padrão em qualquer ambiente&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 27 (final, &lt;a href=&quot;https://openjdk.org/jeps/523&quot;&gt;JEP 523&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Desde o Java 9 (&lt;a href=&quot;https://openjdk.org/jeps/248&quot;&gt;JEP 248&lt;/a&gt;, veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-11/#g1-como-coletor-padr%C3%A3o&quot;&gt;G1 como coletor padrão no post do Java 11&lt;/a&gt;), o G1 era o padrão apenas em máquinas “server”. Com 1 CPU ou menos de 1792 MB de memória física, a JVM escolhia o Serial, um coletor mais simples, que usa uma única thread. Assim, a mesma aplicação podia rodar com coletores diferentes conforme a máquina.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; A JEP 523 afirma que o G1 ficou competitivo com o Serial em qualquer tamanho de heap, em parte graças à JEP 522. Por isso, sem um coletor na linha de comando, a JVM agora escolhe &lt;strong&gt;sempre o G1&lt;/strong&gt;. O Serial continua disponível com &lt;code&gt;-XX:+UseSerialGC&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cuidados.&lt;/strong&gt; Na prática, isso atinge principalmente containers com limites baixos, porque a JVM considera os limites do container ao contar CPUs e memória (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-11/#jvm-ciente-de-cont%C3%AAineres&quot;&gt;JVM ciente de contêineres no post do Java 11&lt;/a&gt;). Se o limite é 1 CPU ou menos de 1792 MB e ninguém escolheu o coletor, o Java 27 passa a rodar G1. As flags &lt;code&gt;AlwaysActAsServerClassMachine&lt;/code&gt; e &lt;code&gt;NeverActAsServerClassMachine&lt;/code&gt;, que influenciavam essa escolha, foram depreciadas no Java 26 (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas de release do 26&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;compact-object-headers-ligados-por-padrão&quot;&gt;Compact object headers ligados por padrão&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 24 (experimental, &lt;a href=&quot;https://openjdk.org/jeps/450&quot;&gt;JEP 450&lt;/a&gt;) → Java 25 (final, &lt;a href=&quot;https://openjdk.org/jeps/519&quot;&gt;JEP 519&lt;/a&gt;) → Java 27 (final, &lt;a href=&quot;https://openjdk.org/jeps/534&quot;&gt;JEP 534&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Cada objeto Java carrega um cabeçalho com dados que a JVM usa internamente, como o hash, a idade do objeto para o GC e um ponteiro para a classe. Em arquiteturas de 64 bits, esse cabeçalho ocupava 96 bits; com compact object headers, ocupa 64. Como a maioria dos objetos é pequena (a &lt;a href=&quot;https://openjdk.org/jeps/450&quot;&gt;JEP 450&lt;/a&gt; cita tamanhos médios de 32 a 64 bytes), o cabeçalho sozinho podia ocupar mais de 20% dos dados vivos, e os 32 bits economizados em cada objeto fazem diferença.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; No Java 25 o recurso já era de produto, mas era preciso pedir com &lt;code&gt;-XX:+UseCompactObjectHeaders&lt;/code&gt; (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#compact-object-headers&quot;&gt;Compact object headers no post do Java 25&lt;/a&gt;). No 27, esse é o layout padrão. A JEP 534 cita os experimentos que motivaram a mudança, entre eles um cenário em que o SPECjbb2015 usou 22% menos heap e 8% menos CPU, o uso em centenas de serviços em produção na Amazon e a adoção como padrão no SapMachine, a distribuição da SAP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cuidados.&lt;/strong&gt; Para voltar ao layout antigo, use &lt;code&gt;-XX:-UseCompactObjectHeaders&lt;/code&gt;. As &lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do Java 27&lt;/a&gt; avisam que essa flag deve ser depreciada e removida no futuro. O JDK traz arquivos CDS (Class Data Sharing, com metadados de classes já processados para acelerar o startup) separados para cada modo, então desligar o recurso não faz perder esse ganho.&lt;/p&gt;
&lt;h3 id=&quot;cache-aot-com-qualquer-coletor-inclusive-zgc&quot;&gt;Cache AOT com qualquer coletor, inclusive ZGC&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 26 (final, &lt;a href=&quot;https://openjdk.org/jeps/516&quot;&gt;JEP 516&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;O cache AOT (ahead-of-time, “antes da execução”) do Project Leyden (&lt;a href=&quot;https://openjdk.org/jeps/483&quot;&gt;JEP 483&lt;/a&gt;, Java 24, e &lt;a href=&quot;https://openjdk.org/jeps/514&quot;&gt;JEP 514&lt;/a&gt;, Java 25) melhora startup e warmup. Numa &lt;strong&gt;execução de treino&lt;/strong&gt;, a JVM observa a aplicação e grava num arquivo as classes já carregadas e ligadas, além de objetos Java prontos. Nas execuções seguintes, ela reaproveita esse arquivo em vez de refazer o trabalho. O funcionamento está no &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#cache-aot-inicializa%C3%A7%C3%A3o-e-warmup-mais-r%C3%A1pidos-projeto-leyden&quot;&gt;post do Java 25&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Até o Java 25, os objetos Java do cache ficavam num formato ligado ao layout de memória dos coletores Serial, Parallel e G1, incompatível com o ZGC. Era preciso escolher entre a latência baixa do ZGC e o startup rápido do cache.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; A JEP 516 cria um formato &lt;strong&gt;independente de GC&lt;/strong&gt;, chamado streamable: as referências entre objetos viram índices lógicos, e uma thread em segundo plano recria os objetos no heap enquanto a aplicação sobe. O formato antigo, mapeável, continua existindo: nele, os objetos são mapeados direto na memória do heap. A JVM escolhe o formato na hora de gravar o cache. Se o treino usou ZGC, &lt;code&gt;-XX:-UseCompressedOops&lt;/code&gt; ou heap acima de 32 GB, grava no formato streamable; com compressed oops ligado e heap de até 32 GB, grava no formato mapeável. O formato streamable pode ser forçado com &lt;code&gt;-XX:+AOTStreamableObjects&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;aot-com-zgc.sh&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;bash&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Treino e criação do cache em um passo (fluxo da JEP 514, Java 25)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:+UseZGC&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:AOTCacheOutput=app.aot&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-jar&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;app.jar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Produção usando o cache, agora também com ZGC (Java 26+)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:+UseZGC&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:AOTCache=app.aot&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-jar&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;app.jar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Por padrão, se o cache não puder ser usado, a JVM emite um aviso e segue sem ele. Com &lt;code&gt;-XX:AOTMode=on&lt;/code&gt;, ela aborta a inicialização, o que é útil para garantir em produção que o cache está sendo aproveitado (&lt;a href=&quot;https://openjdk.org/jeps/483&quot;&gt;JEP 483&lt;/a&gt;). No Java 27, &lt;code&gt;-XX:AOTMode=required&lt;/code&gt; passou a ser um alias de &lt;code&gt;on&lt;/code&gt; e é a forma recomendada, porque &lt;code&gt;on&lt;/code&gt; deve ser depreciado e removido (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;). O Java 26 não conhece o valor &lt;code&gt;required&lt;/code&gt;: a JVM não inicia com essa flag.&lt;/p&gt;
&lt;h3 id=&quot;outros-ajustes-de-gc-e-runtime&quot;&gt;Outros ajustes de GC e runtime&lt;/h3&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Mudança, Versão, Fonte&quot;&gt;







































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Mudança&lt;/th&gt;&lt;th&gt;Versão&lt;/th&gt;&lt;th&gt;Fonte&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;G1 passa a lançar &lt;code&gt;OutOfMemoryError&lt;/code&gt; quando o overhead de GC fica excessivo (&lt;code&gt;UseGCOverheadLimit&lt;/code&gt;), como o Parallel já fazia&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;G1 recupera antes objetos humongous que contêm referências, sem esperar a marcação concorrente&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sem &lt;code&gt;-Xms&lt;/code&gt;, o heap inicial passa a ser o mínimo possível (&lt;code&gt;MinHeapSize&lt;/code&gt;), e não mais 1/64 da memória física&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Padrões de &lt;code&gt;-XX:MinHeapFreeRatio&lt;/code&gt;/&lt;code&gt;MaxHeapFreeRatio&lt;/code&gt; no G1 mudam de 40/70 para 0/100, o que na prática desliga esse redimensionamento do heap&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;-XX:InitiatingHeapOccupancyPercent&lt;/code&gt; vira &lt;code&gt;-XX:G1IHOP&lt;/code&gt; (o nome antigo fica como alias depreciado)&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;UseCompressedClassPointers&lt;/code&gt; fica obsoleta: os ponteiros de classe são sempre comprimidos&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;ferramentas&quot;&gt;Ferramentas&lt;/h2&gt;
&lt;h3 id=&quot;jfr-mascara-dados-sensíveis-antes-de-gravar&quot;&gt;JFR mascara dados sensíveis antes de gravar&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 27 (final, &lt;a href=&quot;https://openjdk.org/jeps/536&quot;&gt;JEP 536&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; O JDK Flight Recorder (JFR) é o gravador de eventos de diagnóstico embutido na JVM. Toda gravação guarda os argumentos da linha de comando, as variáveis de ambiente e as system properties iniciais. É útil para diagnóstico, mas senhas passadas por &lt;code&gt;-D&lt;/code&gt;, tokens em variáveis de ambiente e argumentos como &lt;code&gt;--dbpassword&lt;/code&gt; iam parar, sem nenhuma proteção, no arquivo &lt;code&gt;.&lt;wbr&gt;jfr&lt;/code&gt; que depois é compartilhado ou anexado a um chamado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; A partir do Java 27, o JFR &lt;strong&gt;mascara por padrão&lt;/strong&gt;, ainda dentro do processo e antes de escrever o arquivo, os valores que batem com uma lista de filtros. Para chaves, a lista inclui padrões como &lt;code&gt;*password*&lt;/code&gt;, &lt;code&gt;*secret*&lt;/code&gt;, &lt;code&gt;*token*&lt;/code&gt;, &lt;code&gt;*auth*&lt;/code&gt; e &lt;code&gt;*api*key*&lt;/code&gt;. Para argumentos, cobre formas como &lt;code&gt;-*password *&lt;/code&gt;, que pega a opção e o valor seguinte. O valor mascarado aparece como &lt;code&gt;[REDACTED]&lt;/code&gt;. Dá para acrescentar filtros próprios, carregá-los de arquivo ou desligar os padrões:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:16&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;jfr-mascaramento.sh&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;bash&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Padrão no Java 27: segredos óbvios já saem como [REDACTED]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:StartFlightRecording:filename=dump.jfr&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-jar&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;app.jar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Acrescentar filtros próprios aos padrões (note o &quot;+&quot;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:FlightRecorderOptions:&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;redact-key=+confidencial,redact-argument=+--pin *&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:StartFlightRecording:filename=dump.jfr&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-jar&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;app.jar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Filtros em arquivo e log de depuração do que foi mascarado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;-XX:FlightRecorderOptions:redact-argument=@args.txt,redact-key=@keys.txt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-Xlog:jfr+redact=debug&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:StartFlightRecording:filename=dump.jfr&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-jar&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;app.jar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Conferir o resultado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;jfr &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--events&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;InitialSystemProperty,JVMInformation,InitialEnvironmentVariable&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;dump.jfr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;# Desligar os filtros padrão (só se houver motivo)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-XX:FlightRecorderOptions:redact-key=none,redact-argument=none&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;-jar&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;app.jar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Cuidados.&lt;/strong&gt; Sem o &lt;code&gt;+&lt;/code&gt;, os filtros informados substituem a lista padrão em vez de complementá-la (&lt;a href=&quot;https://openjdk.org/jeps/536&quot;&gt;JEP 536&lt;/a&gt;; o &lt;code&gt;+&lt;/code&gt; e o &lt;code&gt;none&lt;/code&gt; também aparecem nas &lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do Java 27&lt;/a&gt;). Os filtros padrão reconhecem nomes comuns, como &lt;code&gt;password&lt;/code&gt; e &lt;code&gt;token&lt;/code&gt;; um segredo com nome próprio da aplicação só é mascarado se você acrescentar um filtro para ele. No mesmo release, o evento &lt;code&gt;jdk.&lt;wbr&gt;SystemProcess&lt;/code&gt; deixou de registrar os argumentos de linha de comando de outros processos da máquina.&lt;/p&gt;
&lt;h3 id=&quot;diagnóstico-e-ferramentas-menores&quot;&gt;Diagnóstico e ferramentas menores&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java 26:&lt;/strong&gt; javadoc com tema escuro; o thread dump de &lt;code&gt;jcmd &amp;#x3C;pid&gt; Thread.&lt;wbr&gt;dump_to_file&lt;/code&gt; mostra o dono do lock de threads estacionadas (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas do 26&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java 27:&lt;/strong&gt; novo &lt;code&gt;jcmd &amp;#x3C;pid&gt; VM.&lt;wbr&gt;security_properties&lt;/code&gt;, script de autocompletar do &lt;code&gt;jcmd&lt;/code&gt; para Bash, &lt;code&gt;-XX:FlightRecorderOptions:help&lt;/code&gt; e contagem de file descriptors abertos em &lt;code&gt;VM.&lt;wbr&gt;info&lt;/code&gt; e no &lt;code&gt;hs_err_pid&lt;/code&gt; (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;segurança&quot;&gt;Segurança&lt;/h2&gt;
&lt;h3 id=&quot;troca-de-chaves-híbrida-pós-quântica-no-tls-13&quot;&gt;Troca de chaves híbrida pós-quântica no TLS 1.3&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 27 (final, &lt;a href=&quot;https://openjdk.org/jeps/527&quot;&gt;JEP 527&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Este recurso usa o ML-KEM, algoritmo resistente a computação quântica que entrou no Java 24 (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#criptografia-resistente-a-computa%C3%A7%C3%A3o-qu%C3%A2ntica-ml-kem-e-ml-dsa&quot;&gt;ML-KEM e ML-DSA no post do Java 25&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Um atacante pode gravar tráfego cifrado hoje e decifrá-lo quando existirem computadores quânticos capazes de quebrar RSA e ECDH. É o ataque conhecido como “harvest now, decrypt later”. A IETF definiu esquemas &lt;strong&gt;híbridos&lt;/strong&gt; para o TLS 1.3, que combinam um algoritmo resistente a ataques quânticos (ML-KEM) com um tradicional (ECDHE). O resultado continua seguro enquanto pelo menos um dos dois resistir.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; No TLS, os &lt;strong&gt;named groups&lt;/strong&gt; são os algoritmos de troca de chaves que cliente e servidor negociam no início da conexão (o handshake). O JDK implementa três named groups híbridos: &lt;code&gt;X25519MLKEM768&lt;/code&gt;, &lt;code&gt;SecP256r1MLKEM768&lt;/code&gt; e &lt;code&gt;SecP384r1MLKEM1024&lt;/code&gt;. O &lt;code&gt;X25519MLKEM768&lt;/code&gt; vai para o &lt;strong&gt;topo da lista padrão&lt;/strong&gt;, então quem usa &lt;code&gt;javax.&lt;wbr&gt;net.&lt;wbr&gt;ssl&lt;/code&gt; sem escolher grupos passa a oferecê-lo sem mudar código. Os outros dois só são usados se forem configurados. A lista padrão completa fica assim: &lt;code&gt;X25519MLKEM768, x25519, secp256r1, secp384r1, secp521r1, x448, ffdhe2048, ffdhe3072, ffdhe4096&lt;/code&gt;. Para restringir ou reordenar, use a propriedade &lt;code&gt;jdk.&lt;wbr&gt;tls.&lt;wbr&gt;namedGroups&lt;/code&gt; ou &lt;code&gt;SSLParameters.&lt;wbr&gt;setNamedGroups&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:18&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;TlsHibrido.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;javax&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SSLContext&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;javax&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SSLParameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;javax&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;net&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ssl&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SSLSocket&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;TlsHibrido&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SSLSocket&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; socket &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;SSLSocket&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; SSLContext&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getDefault&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getSocketFactory&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;createSocket&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SSLParameters&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; socket&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getSSLParameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Só é preciso mexer aqui se a política exigir grupos específicos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setNamedGroups&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;X25519MLKEM768&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;SecP256r1MLKEM768&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;x25519&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;secp256r1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;socket&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setSSLParameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; socket&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getSSLParameters&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getNamedGroups&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// X25519MLKEM768, SecP256r1MLKEM768, x25519, secp256r1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;outras-mudanças-de-segurança&quot;&gt;Outras mudanças de segurança&lt;/h3&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Mudança, Versão, Fonte&quot;&gt;







































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Mudança&lt;/th&gt;&lt;th&gt;Versão&lt;/th&gt;&lt;th&gt;Fonte&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Novo algoritmo de &lt;code&gt;Cipher&lt;/code&gt; &lt;code&gt;&quot;HPKE&quot;&lt;/code&gt; (Hybrid Public Key Encryption, RFC 9180) com &lt;code&gt;HPKEParameterSpec&lt;/code&gt;&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Assinatura e verificação de JARs com ML-DSA (&lt;code&gt;jarsigner&lt;/code&gt; e API &lt;code&gt;JarSigner&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Nova propriedade &lt;code&gt;jdk.&lt;wbr&gt;crypto.&lt;wbr&gt;disabledAlgorithms&lt;/code&gt; para desabilitar algoritmos na camada JCE&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Compressão de certificados TLS 1.3 com zlib (RFC 8879), ligada por padrão&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Chaves privadas ML-KEM e ML-DSA passam a ser codificadas em PKCS#8 no formato &lt;code&gt;seed&lt;/code&gt; por padrão&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Otimizações de desempenho em ML-KEM e ML-DSA (SHA-3 em x86_64 com AVX-512) e em X25519/Ed25519 (AArch64 e x86_64)&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;removidos-e-depreciados&quot;&gt;Removidos e depreciados&lt;/h2&gt;
&lt;h3 id=&quot;mutação-de-campos-final-por-reflexão-passa-a-emitir-aviso&quot;&gt;Mutação de campos final por reflexão passa a emitir aviso&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 26 (final, &lt;a href=&quot;https://openjdk.org/jeps/500&quot;&gt;JEP 500&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Desde o JDK 5, &lt;code&gt;Field.&lt;wbr&gt;setAccessible(true)&lt;/code&gt; seguido de &lt;code&gt;Field.&lt;wbr&gt;set(...)&lt;/code&gt; altera até campos &lt;code&gt;final&lt;/code&gt;. Com isso, nem a JVM nem quem lê o código podem confiar que um &lt;code&gt;final&lt;/code&gt; de instância nunca muda. Para a JVM, isso bloqueia otimizações como o &lt;strong&gt;constant folding&lt;/strong&gt;, em que o compilador JIT troca a leitura do campo pelo próprio valor (é o que dá desempenho às &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#lazy-constants&quot;&gt;Lazy Constants&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou.&lt;/strong&gt; No Java 26, alterar um campo &lt;code&gt;final&lt;/code&gt; por reflexão ainda funciona, mas gera um &lt;strong&gt;aviso&lt;/strong&gt;, no máximo um por módulo. A JEP prevê que uma versão futura passe a &lt;strong&gt;lançar exceção&lt;/strong&gt; por padrão. O comportamento é controlado por &lt;code&gt;--illegal-final-field-mutation=allow|warn|debug|deny&lt;/code&gt; (&lt;code&gt;warn&lt;/code&gt; é o padrão no 26), e a permissão é dada explicitamente com &lt;code&gt;--enable-final-field-mutation=ALL-UNNAMED&lt;/code&gt; ou com uma lista de módulos. &lt;code&gt;--add-opens&lt;/code&gt;, a opção usada desde o &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-17/#encapsulamento-forte-dos-internos-do-jdk&quot;&gt;encapsulamento forte do Java 16 e 17&lt;/a&gt; para liberar reflexão profunda, não basta para evitar o aviso.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:20&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;FinalMutavel.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;reflect&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Field&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;FinalMutavel&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Preco&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Preco&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;centavos &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Preco&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; preco &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Preco&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1_000&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Field&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; campo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Preco&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getDeclaredField&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;campo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setAccessible&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// continua funcionando como antes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;campo&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;preco&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#ccacc8&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;--0:#515553;--0fs:italic;--1:#b2b7b5;--1fs:italic&quot;&gt;// Java 26+: gera WARNING (padrão warn)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;preco&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;centavos&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Saída no Temurin 26.0.2:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;saída&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;WARNING: Final field centavos in class FinalMutavel$Preco has been mutated reflectively by class FinalMutavel in unnamed module @525b461a (file:/w/FinalMutavel.java)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;WARNING: Use --enable-final-field-mutation=ALL-UNNAMED to avoid a warning&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;WARNING: Mutating final fields will be blocked in a future release unless final field mutation is enabled&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Cuidados.&lt;/strong&gt; Com &lt;code&gt;--illegal-final-field-mutation=deny&lt;/code&gt;, o mesmo código lança &lt;code&gt;IllegalAccessException&lt;/code&gt;. A JEP recomenda rodar os testes com &lt;code&gt;deny&lt;/code&gt; desde já para achar quem faz isso, e em geral o culpado é uma biblioteca, não a aplicação. Outra forma de encontrar é o evento JFR &lt;code&gt;jdk.&lt;wbr&gt;FinalFieldMutation&lt;/code&gt;. Para bibliotecas de serialização, a JEP recomenda &lt;code&gt;sun.&lt;wbr&gt;reflect.&lt;wbr&gt;ReflectionFactory&lt;/code&gt; em vez de reflexão profunda.&lt;/p&gt;
&lt;h3 id=&quot;applet-api-removida&quot;&gt;Applet API removida&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 9 (depreciado, &lt;a href=&quot;https://openjdk.org/jeps/289&quot;&gt;JEP 289&lt;/a&gt;) → Java 17 (depreciado para remoção, &lt;a href=&quot;https://openjdk.org/jeps/398&quot;&gt;JEP 398&lt;/a&gt;) → Java 26 (removido, &lt;a href=&quot;https://openjdk.org/jeps/504&quot;&gt;JEP 504&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Os navegadores já não executam applets, e desde o Java 11, quando o &lt;code&gt;appletviewer&lt;/code&gt; foi removido, o JDK não tem mais como rodá-los (&lt;a href=&quot;https://openjdk.org/jeps/504&quot;&gt;JEP 504&lt;/a&gt;; veja também &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-11/#nashorn-pack200-cms-e-applet-api&quot;&gt;Nashorn, Pack200, CMS e Applet API no post do Java 11&lt;/a&gt;). Faltava remover a API. No Java 26 saíram o pacote &lt;code&gt;java.&lt;wbr&gt;applet&lt;/code&gt; inteiro, &lt;code&gt;javax.&lt;wbr&gt;swing.&lt;wbr&gt;JApplet&lt;/code&gt;, &lt;code&gt;java.&lt;wbr&gt;beans.&lt;wbr&gt;AppletInitializer&lt;/code&gt; e os membros de &lt;code&gt;java.&lt;wbr&gt;beans.&lt;wbr&gt;Beans&lt;/code&gt; e &lt;code&gt;javax.&lt;wbr&gt;swing.&lt;wbr&gt;RepaintManager&lt;/code&gt; que dependiam deles. Um efeito colateral: &lt;code&gt;URL.&lt;wbr&gt;getContent()&lt;/code&gt; e &lt;code&gt;URLConnection.&lt;wbr&gt;getContent()&lt;/code&gt; não devolvem mais &lt;code&gt;java.&lt;wbr&gt;applet.&lt;wbr&gt;AudioClip&lt;/code&gt; para conteúdo de áudio. Para tocar áudio, a JEP aponta a &lt;code&gt;javax.&lt;wbr&gt;sound.&lt;wbr&gt;SoundClip&lt;/code&gt;, introduzida no Java 25.&lt;/p&gt;
&lt;h3 id=&quot;outras-remoções&quot;&gt;Outras remoções&lt;/h3&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Removido, Versão, Fonte&quot;&gt;

















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Removido&lt;/th&gt;&lt;th&gt;Versão&lt;/th&gt;&lt;th&gt;Fonte&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Thread.&lt;wbr&gt;stop()&lt;/code&gt;: código que chama não compila, e binários antigos recebem &lt;code&gt;NoSuchMethodError&lt;/code&gt;&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Ferramenta &lt;code&gt;jrunscript&lt;/code&gt; e módulo &lt;code&gt;jdk.&lt;wbr&gt;jsobject&lt;/code&gt; (este segue no JavaFX)&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Suporte a InfiniBand SDP, &lt;code&gt;setTTL&lt;/code&gt;/&lt;code&gt;getTTL&lt;/code&gt; de &lt;code&gt;MulticastSocket&lt;/code&gt; e &lt;code&gt;DatagramSocketImpl&lt;/code&gt; e &lt;code&gt;MulticastSocket.&lt;wbr&gt;send(DatagramPacket, byte)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;Notas do 26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JVM Compiler Interface (JVMCI, a interface para plugar na JVM um compilador JIT escrito em Java, &lt;a href=&quot;https://openjdk.org/jeps/243&quot;&gt;JEP 243&lt;/a&gt;): módulos &lt;code&gt;jdk.&lt;wbr&gt;internal.&lt;wbr&gt;vm.&lt;wbr&gt;ci&lt;/code&gt;, &lt;code&gt;jdk.&lt;wbr&gt;graal.&lt;wbr&gt;compiler&lt;/code&gt; e &lt;code&gt;jdk.&lt;wbr&gt;graal.&lt;wbr&gt;compiler.&lt;wbr&gt;management&lt;/code&gt;, flags &lt;code&gt;*JVMCI*&lt;/code&gt; e &lt;code&gt;-XX:+UseGraalJIT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Opções &lt;code&gt;-noclassgc&lt;/code&gt;, &lt;code&gt;-noverify&lt;/code&gt;, &lt;code&gt;-verifyremote&lt;/code&gt; e &lt;code&gt;-Xverify:none&lt;/code&gt;&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ThreadPoolExecutor.&lt;wbr&gt;finalize()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Mecanismo &lt;code&gt;VFORK&lt;/code&gt; de &lt;code&gt;jdk.&lt;wbr&gt;lang.&lt;wbr&gt;Process.&lt;wbr&gt;launchMechanism&lt;/code&gt; (Linux) e a propriedade &lt;code&gt;java.&lt;wbr&gt;locale.&lt;wbr&gt;useOldISOCodes&lt;/code&gt;&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ffdhe6144&lt;/code&gt; e &lt;code&gt;ffdhe8192&lt;/code&gt; saem da lista padrão de named groups TLS&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;Notas do 27&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h3 id=&quot;depreciações&quot;&gt;Depreciações&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java 26:&lt;/strong&gt; &lt;code&gt;java.&lt;wbr&gt;net.&lt;wbr&gt;SocketPermission&lt;/code&gt; e &lt;code&gt;Socket.&lt;wbr&gt;setPerformancePreferences&lt;/code&gt; (e os equivalentes em &lt;code&gt;SocketImpl&lt;/code&gt; e &lt;code&gt;ServerSocket&lt;/code&gt;) foram depreciados para remoção. Também foram depreciadas as flags &lt;code&gt;-Xmaxjitcodesize&lt;/code&gt;, &lt;code&gt;AlwaysActAsServerClassMachine&lt;/code&gt;, &lt;code&gt;NeverActAsServerClassMachine&lt;/code&gt;, &lt;code&gt;AggressiveHeap&lt;/code&gt; e &lt;code&gt;MaxRAM&lt;/code&gt;. No caso de &lt;code&gt;MaxRAM&lt;/code&gt;, o valor padrão também deixou de existir, e o dimensionamento do heap usa a memória disponível (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas do 26&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java 27:&lt;/strong&gt; o alias &lt;code&gt;-XX:InitiatingHeapOccupancyPercent&lt;/code&gt; foi depreciado (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java 28 (ainda não lançado):&lt;/strong&gt; port macOS/x64 depreciado para remoção (&lt;a href=&quot;https://openjdk.org/jeps/541&quot;&gt;JEP 541&lt;/a&gt;). Segundo a JEP, os engenheiros da Oracle deixam de manter esse port a partir do JDK 27.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ainda-em-preview-ou-incubadora&quot;&gt;Ainda em preview ou incubadora&lt;/h2&gt;
&lt;p&gt;Nenhum destes recursos é definitivo: todos exigem &lt;code&gt;--enable-preview&lt;/code&gt; (ou &lt;code&gt;--add-modules&lt;/code&gt;, no caso da incubadora) e mudaram de API entre uma versão e outra. Todos já existiam como preview ou incubadora no Java 25; cada seção aponta para a explicação original no post do Java 25 e mostra o que mudou desde então. Os exemplos refletem o Java 27.&lt;/p&gt;
&lt;h3 id=&quot;structured-concurrency&quot;&gt;Structured Concurrency&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 25 (5ª preview, &lt;a href=&quot;https://openjdk.org/jeps/505&quot;&gt;JEP 505&lt;/a&gt;) → Java 26 (6ª preview, &lt;a href=&quot;https://openjdk.org/jeps/525&quot;&gt;JEP 525&lt;/a&gt;) → Java 27 (7ª preview, &lt;a href=&quot;https://openjdk.org/jeps/533&quot;&gt;JEP 533&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;As primeiras versões estão em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-21/#structured-concurrency&quot;&gt;Structured Concurrency no post do Java 21&lt;/a&gt; e &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#structured-concurrency&quot;&gt;no post do Java 25&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Com &lt;code&gt;ExecutorService&lt;/code&gt;, nada liga as tarefas ao método que as disparou: se uma falha, as outras continuam; se quem espera é interrompido, as subtarefas nem ficam sabendo; e o thread dump não mostra quem é filho de quem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Como funciona.&lt;/strong&gt; &lt;code&gt;StructuredTaskScope&lt;/code&gt; trata um grupo de subtarefas como uma unidade presa a um bloco &lt;code&gt;try&lt;/code&gt;. A thread que abre o escopo, chamada de thread dona, dispara as subtarefas com &lt;code&gt;fork&lt;/code&gt; (por padrão, cada uma numa virtual thread), espera tudo com &lt;code&gt;join&lt;/code&gt; e fecha o escopo ao sair do bloco. A política de conclusão fica num &lt;code&gt;Joiner&lt;/code&gt;. Na política padrão, se uma subtarefa falhar, as outras são canceladas. O &lt;code&gt;close()&lt;/code&gt; sempre espera as threads terminarem, então nenhuma sobra depois do bloco. No thread dump em JSON (&lt;code&gt;jcmd &amp;#x3C;pid&gt; Thread.&lt;wbr&gt;dump_to_file -format=json &amp;#x3C;arquivo&gt;&lt;/code&gt;), a hierarquia de escopos aparece.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/java-29/structured-concurrency.svg&quot; alt=&quot;Diagrama do StructuredTaskScope no Java 27: a thread dona abre o escopo, dispara três subtarefas em virtual threads e chama join; com os Joiners prontos, os três desfechos são sucesso com resultado, falha de uma subtarefa com ExecutionException e prazo estourado com ExecutionException causada por CancelledByTimeoutException&quot;&gt;&lt;/p&gt;
&lt;p&gt;O diagrama mostra os três desfechos possíveis do &lt;code&gt;join()&lt;/code&gt; com os &lt;code&gt;Joiner&lt;/code&gt;s prontos do Java 27. O exemplo abaixo cobre a política padrão e um &lt;code&gt;Joiner&lt;/code&gt; com prazo:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:62&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Checkout.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutionException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CancelledByTimeoutException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Joiner&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Subtask&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Checkout&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Resumo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cliente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; itens&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; buscarCliente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;ana&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; contarItens&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;150&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; consultarEstoque&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sku&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sku&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;lento&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;5_000&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sku &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;: disponível&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Política padrão: se uma subtarefa falhar, as outras são canceladas&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Resumo&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; carregar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutionException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Subtask&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cliente &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fork&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; buscarCliente&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Subtask&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Integer&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; itens &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fork&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; contarItens&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#515553;--0fs:italic;--1:#b2b7b5;--1fs:italic&quot;&gt;// Java 27: lança ExecutionException se alguma falhar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Resumo&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;cliente&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; itens&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Todas precisam dar certo dentro do prazo; o resultado já vem como lista&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; estoque&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; skus&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; prazo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutionException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Joiner&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;allSuccessfulOrThrow&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;cf &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cf&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;withTimeout&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;prazo&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;)))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;skus&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sku &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fork&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; consultarEstoque&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sku&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;carregar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;estoque&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;a1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;b2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofSeconds&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;estoque&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;a1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;lento&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofMillis&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutionException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getCause&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CancelledByTimeoutException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;prazo estourado: subtarefas canceladas&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para rodar no Java 27: &lt;code&gt;java --enable-preview --source 27 Checkout.&lt;wbr&gt;java&lt;/code&gt;. Pela API do JDK 27, a saída esperada é:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:3&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;saída&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Resumo[cliente=ana, itens=3]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;[a1: disponível, b2: disponível]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;prazo estourado: subtarefas canceladas&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A lista do segundo passo vem na ordem em que as subtarefas foram disparadas com &lt;code&gt;fork&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou no caminho.&lt;/strong&gt; Cada preview mexeu na API, e código escrito para uma versão costuma não compilar na seguinte:&lt;/p&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Versão, Mudanças na API&quot;&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Versão&lt;/th&gt;&lt;th&gt;Mudanças na API&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Java 25 (&lt;a href=&quot;https://openjdk.org/jeps/505&quot;&gt;JEP 505&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;Os construtores públicos deram lugar às fábricas estáticas &lt;code&gt;open(...)&lt;/code&gt; e a política passou para o &lt;code&gt;Joiner&lt;/code&gt;. Em caso de falha, &lt;code&gt;join()&lt;/code&gt; lançava &lt;code&gt;FailedException&lt;/code&gt;; com prazo estourado, &lt;code&gt;TimeoutException&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Java 26 (&lt;a href=&quot;https://openjdk.org/jeps/525&quot;&gt;JEP 525&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;Novo &lt;code&gt;Joiner.&lt;wbr&gt;onTimeout()&lt;/code&gt;, para um &lt;code&gt;Joiner&lt;/code&gt; devolver resultado quando o prazo estoura. &lt;code&gt;allSuccessfulOrThrow()&lt;/code&gt; passou a devolver uma lista de resultados, e não mais um stream de subtarefas. &lt;code&gt;anySuccessfulResultOrThrow()&lt;/code&gt; foi renomeado para &lt;code&gt;anySuccessfulOrThrow()&lt;/code&gt;. O &lt;code&gt;open&lt;/code&gt; que recebe &lt;code&gt;Joiner&lt;/code&gt; e configuração passou a aceitar &lt;code&gt;UnaryOperator&lt;/code&gt; em vez de &lt;code&gt;Function&lt;/code&gt;. As exceções de &lt;code&gt;join()&lt;/code&gt; continuaram as mesmas.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Java 27 (&lt;a href=&quot;https://openjdk.org/jeps/533&quot;&gt;JEP 533&lt;/a&gt;)&lt;/td&gt;&lt;td&gt;&lt;code&gt;StructuredTaskScope&lt;/code&gt; e &lt;code&gt;Joiner&lt;/code&gt; ganharam um terceiro parâmetro de tipo, &lt;code&gt;R_X&lt;/code&gt;, com a exceção que &lt;code&gt;join()&lt;/code&gt; pode lançar. As fábricas prontas passaram a lançar &lt;code&gt;ExecutionException&lt;/code&gt;, e há sobrecargas que recebem uma &lt;code&gt;Function&lt;/code&gt; para gerar outra exceção. &lt;code&gt;FailedException&lt;/code&gt; e &lt;code&gt;TimeoutException&lt;/code&gt; deixaram de existir. &lt;code&gt;awaitAll()&lt;/code&gt; foi removido. &lt;code&gt;onTimeout()&lt;/code&gt; virou &lt;code&gt;timeout()&lt;/code&gt;, e o estouro de prazo chega como exceção com causa &lt;code&gt;CancelledByTimeoutException&lt;/code&gt;. Também entrou o &lt;code&gt;open(UnaryOperator)&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Na prática, o tratamento de erro escrito para o 26 precisa mudar no 27:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:6&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;TratamentoDeErro.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; scope &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; StructuredTaskScope&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;open&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight del&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#505957;--1:#aab1ad&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#505957;--1:#aab1ad&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;StructuredTaskScope.FailedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#505957;--1:#aab1ad&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#505957;--1:#aab1ad&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#525755;--0fs:italic;--1:#abb0ae;--1fs:italic&quot;&gt;// Java 26&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight ins&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9bb4ff&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9bb4ff&quot;&gt;ExecutionException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#525755;--0fs:italic;--1:#b2b7b5;--1fs:italic&quot;&gt;// Java 27&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Throwable&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; causa &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getCause&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                 &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// exceção da subtarefa que falhou&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Um &lt;code&gt;Joiner&lt;/code&gt; próprio implementa &lt;code&gt;result()&lt;/code&gt; e, a partir do 27, &lt;code&gt;timeout()&lt;/code&gt;; &lt;code&gt;onFork&lt;/code&gt; e &lt;code&gt;onComplete&lt;/code&gt; têm implementação default. As assinaturas completas estão na JEP 533 e no &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java&quot;&gt;código-fonte do &lt;code&gt;StructuredTaskScope&lt;/code&gt; na tag &lt;code&gt;jdk-27-ga&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Existe uma JEP candidata, a &lt;a href=&quot;https://openjdk.org/jeps/543&quot;&gt;JEP 543&lt;/a&gt;, que propõe finalizar a API no Java 28 sem outras mudanças. Em 16/09/2026 ela ainda não tinha alvo no 28.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quando usar.&lt;/strong&gt; Quando uma operação se divide em subtarefas concorrentes que só fazem sentido juntas, como buscar dados de vários serviços para montar uma resposta. Enquanto a API estiver em preview, concentre o uso em poucos pontos do código: a cada versão do JDK, é ali que o ajuste vai ser necessário.&lt;/p&gt;
&lt;h3 id=&quot;tipos-primitivos-em-patterns-instanceof-e-switch&quot;&gt;Tipos primitivos em patterns, instanceof e switch&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 25 (3ª preview, &lt;a href=&quot;https://openjdk.org/jeps/507&quot;&gt;JEP 507&lt;/a&gt;) → Java 26 (4ª preview, &lt;a href=&quot;https://openjdk.org/jeps/530&quot;&gt;JEP 530&lt;/a&gt;) → Java 27 (5ª preview, &lt;a href=&quot;https://openjdk.org/jeps/532&quot;&gt;JEP 532&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A versão do Java 25 está em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#tipos-primitivos-em-padr%C3%B5es-instanceof-e-switch&quot;&gt;Tipos primitivos em padrões, instanceof e switch no post do Java 25&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Converter um primitivo para outro menor, como &lt;code&gt;int&lt;/code&gt; para &lt;code&gt;byte&lt;/code&gt;, é silencioso: se o valor não cabe, o cast corta bits e o erro segue adiante sem aviso. O &lt;code&gt;instanceof&lt;/code&gt; sempre serviu para perguntar “é seguro fazer este cast?”, mas só funcionava com tipos de referência. Um &lt;code&gt;switch&lt;/code&gt; também não aceitava &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt; nem &lt;code&gt;boolean&lt;/code&gt; como seletor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Como funciona.&lt;/strong&gt; Com o recurso habilitado, &lt;code&gt;instanceof&lt;/code&gt; e &lt;code&gt;switch&lt;/code&gt; aceitam tipos primitivos em qualquer posição de pattern. O teste vale &lt;code&gt;true&lt;/code&gt; quando a conversão é &lt;strong&gt;exata&lt;/strong&gt;, ou seja, quando nenhuma informação se perde. Com &lt;code&gt;int i = 1000&lt;/code&gt;, &lt;code&gt;i instanceof byte&lt;/code&gt; é &lt;code&gt;false&lt;/code&gt;. Com &lt;code&gt;i = 16_777_217&lt;/code&gt;, &lt;code&gt;i instanceof float&lt;/code&gt; também é &lt;code&gt;false&lt;/code&gt;, porque o &lt;code&gt;float&lt;/code&gt; não representa esse inteiro sem perder precisão. O &lt;code&gt;switch&lt;/code&gt; passa a funcionar com todos os tipos primitivos e com os wrappers correspondentes. Um &lt;code&gt;switch&lt;/code&gt; sobre &lt;code&gt;boolean&lt;/code&gt; que trata &lt;code&gt;true&lt;/code&gt; e &lt;code&gt;false&lt;/code&gt; já é exaustivo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou no caminho.&lt;/strong&gt; A JEP 530 (Java 26) mudou duas coisas: melhorou a definição de conversão “incondicionalmente exata” e deixou mais rígida a checagem de dominância no &lt;code&gt;switch&lt;/code&gt;. Com isso, o compilador passa a rejeitar &lt;code&gt;case&lt;/code&gt; que nunca seriam alcançados, e alguns &lt;code&gt;switch&lt;/code&gt; que compilavam no Java 25 deixam de compilar. A JEP 532 (Java 27) repete o preview sem mudanças, então quem já ajustou o código para o 26 não precisa mexer de novo.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:38&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;PadroesPrimitivos.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;PadroesPrimitivos&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// instanceof com tipo primitivo: true só se a conversão for exata&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; classificar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;cabe em byte: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;precisa de int: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// switch sobre double, com constante e guarda&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; descrever&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; temperatura&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;temperatura&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0d&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;zero&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; t when t &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;negativa: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;positiva: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; t&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// switch sobre boolean: true + false já é exaustivo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; estado&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;boolean&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ativo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ativo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;ligado&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;desligado&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;classificar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// cabe em byte: 42&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;classificar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// precisa de int: 1000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;descrever&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3.5&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// negativa: -3.5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;estado&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// ligado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; grande &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;16_777_217L&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;       &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 2^24 + 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;grande &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// false: float perderia precisão&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;grande &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para rodar: &lt;code&gt;java --enable-preview --source 27 PadroesPrimitivos.&lt;wbr&gt;java&lt;/code&gt; (no Java 26, &lt;code&gt;--source 26&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;A checagem de dominância mais rígida também pega constantes que um pattern anterior já cobre. O trecho abaixo compila no Java 25 com &lt;code&gt;--enable-preview&lt;/code&gt; e é rejeitado a partir do 26:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:8&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Dominancia.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; teste&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; f &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#515553;--0fs:italic;--1:#b2b7b5;--1fs:italic&quot;&gt;// erro: &quot;this case label is dominated by a preceding case label&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#ccacc8&quot;&gt;16_777_216&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#295e45;--1:#86C3A2&quot;&gt;constante&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;outro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;lazy-constants&quot;&gt;Lazy Constants&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 25 (preview, &lt;a href=&quot;https://openjdk.org/jeps/502&quot;&gt;JEP 502&lt;/a&gt;) → Java 26 (2ª preview, &lt;a href=&quot;https://openjdk.org/jeps/526&quot;&gt;JEP 526&lt;/a&gt;) → Java 27 (3ª preview, &lt;a href=&quot;https://openjdk.org/jeps/531&quot;&gt;JEP 531&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;No Java 25, a API se chamava Stable Values (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#stable-values&quot;&gt;Stable Values no post do Java 25&lt;/a&gt;); o nome Lazy Constants veio no Java 26.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; Um campo &lt;code&gt;final&lt;/code&gt; precisa ser atribuído no construtor ou no inicializador estático, ou seja, cedo. Se o valor é caro de montar (um logger que lê configuração, uma conexão, um cache), a aplicação paga esse custo na subida, mesmo que nunca use o valor. As saídas de sempre têm seus problemas: o padrão da classe holder só serve para campos &lt;code&gt;static&lt;/code&gt;, o double-checked locking exige &lt;code&gt;volatile&lt;/code&gt; e é fácil de errar, e o &lt;code&gt;ConcurrentHashMap.&lt;wbr&gt;computeIfAbsent&lt;/code&gt; impede que a JVM trate o valor como constante.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Como funciona.&lt;/strong&gt; Um &lt;code&gt;java.&lt;wbr&gt;lang.&lt;wbr&gt;LazyConstant&amp;#x3C;T&gt;&lt;/code&gt; nasce vazio, com uma função de cálculo. O primeiro &lt;code&gt;get()&lt;/code&gt; executa a função e guarda o resultado. A função roda &lt;strong&gt;no máximo uma vez&lt;/strong&gt;, mesmo com várias threads chamando &lt;code&gt;get()&lt;/code&gt; ao mesmo tempo, e depois disso o conteúdo não muda. Segundo a JEP, o conteúdo fica num campo com a anotação interna &lt;code&gt;@Stable&lt;/code&gt;; se a lazy constant estiver num campo &lt;code&gt;final&lt;/code&gt;, a JVM pode aplicar constant folding (explicado na seção da &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#muta%C3%A7%C3%A3o-de-campos-final-por-reflex%C3%A3o-passa-a-emitir-aviso&quot;&gt;JEP 500&lt;/a&gt;) como faria com um &lt;code&gt;final&lt;/code&gt; comum. Existem também versões preguiçosas das coleções: &lt;code&gt;List.&lt;wbr&gt;ofLazy&lt;/code&gt;, &lt;code&gt;Map.&lt;wbr&gt;ofLazy&lt;/code&gt; e, a partir do Java 27, &lt;code&gt;Set.&lt;wbr&gt;ofLazy&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/java-29/lazy-constant.svg&quot; alt=&quot;Diagrama do ciclo de vida de uma LazyConstant (criada, primeiro get, inicializada) e comparação entre campo final, LazyConstant e campo não final em número de atribuições, momento do cálculo, constant folding e escrita concorrente&quot;&gt;&lt;/p&gt;
&lt;p&gt;O diagrama mostra o ciclo de vida de uma lazy constant e a comparação que a JEP 531 faz com campos &lt;code&gt;final&lt;/code&gt; e não &lt;code&gt;final&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:50&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Aplicacao.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;EnumSet&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Aplicacao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Conexao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Worker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Taxa&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; moeda&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Opcao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;VERBOSE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;DRY_RUN&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;STRICT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Computado no primeiro get(), no máximo uma vez, mesmo com várias threads&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;LazyConstant&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Conexao&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CONEXAO &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;LazyConstant&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; abrirConexao&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#295e45;--1:#86C3A2&quot;&gt;jdbc:postgresql://db/app&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Lista de tamanho fixo: cada posição é computada quando acessada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Worker&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; WORKERS &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofLazy&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#ccacc8&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Worker&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;::new&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Mapa com chaves conhecidas: cada valor é computado quando lido&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Taxa&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; TAXAS &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofLazy&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#295e45;--1:#86C3A2&quot;&gt;BRL&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#295e45;--1:#86C3A2&quot;&gt;USD&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Aplicacao&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;carregarTaxa&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Java 27: a pertinência de cada candidato é decidida sob demanda&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;Opcao&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; OPCOES &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Set&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofLazy&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;EnumSet&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;allOf&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Opcao&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Aplicacao&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#9ab3ff&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;habilitada&lt;/span&gt;&lt;span style=&quot;--0:#4f5755;--1:#b1b7b4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Conexao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; abrirConexao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;abrindo conexão (uma única vez)&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Conexao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Taxa&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; carregarTaxa&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; moeda&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;carregando taxa de &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; moeda&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Taxa&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;moeda&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; moeda&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;BRL&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;5.4&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;boolean&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; habilitada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Opcao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; opcao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;avaliando &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; opcao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; opcao &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Opcao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DRY_RUN&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CONEXAO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// computa aqui&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CONEXAO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// devolve o mesmo valor, sem recalcular&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;WORKERS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// só o índice 2 é criado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;TAXAS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;USD&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// só USD é carregado; BRL, não&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;OPCOES&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;contains&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Opcao&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DRY_RUN&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// só DRY_RUN é avaliado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para rodar no Java 27: &lt;code&gt;java --enable-preview --source 27 Aplicacao.&lt;wbr&gt;java&lt;/code&gt;. A saída mostra que cada função de cálculo roda só quando o valor é pedido, e uma única vez:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:8&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;saída&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;abrindo conexão (uma única vez)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Conexao[url=jdbc:postgresql://db/app]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Conexao[url=jdbc:postgresql://db/app]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Worker[id=2]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;carregando taxa de USD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Taxa[moeda=USD, valor=5.4]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;avaliando DRY_RUN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No Java 26, &lt;code&gt;Set.&lt;wbr&gt;ofLazy&lt;/code&gt; não existe. Sem as linhas de &lt;code&gt;OPCOES&lt;/code&gt;, o exemplo roda com &lt;code&gt;--source 26&lt;/code&gt; no Temurin 26.0.2 e imprime as seis primeiras linhas acima.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quando usar.&lt;/strong&gt; Lazy constants fazem sentido para valores caros que talvez nem sejam usados e que, depois de calculados, nunca mudam: configuração, conexões, loggers, tabelas de consulta. Enquanto a API estiver em preview, prefira usá-la em código que você controla e recompila a cada versão do JDK.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou no caminho.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java 26 (JEP 526):&lt;/strong&gt; a API foi renomeada de &lt;code&gt;StableValue&lt;/code&gt; para &lt;code&gt;LazyConstant&lt;/code&gt; e ficou só com os casos de alto nível. Saíram os métodos de baixo nível &lt;code&gt;orElseSet&lt;/code&gt;, &lt;code&gt;setOrThrow&lt;/code&gt; e &lt;code&gt;trySet&lt;/code&gt;, e também as fábricas &lt;code&gt;function&lt;/code&gt; e &lt;code&gt;intFunction&lt;/code&gt;. As fábricas de coleções foram para &lt;code&gt;List.&lt;wbr&gt;ofLazy&lt;/code&gt; e &lt;code&gt;Map.&lt;wbr&gt;ofLazy&lt;/code&gt;, e &lt;code&gt;null&lt;/code&gt; deixou de ser aceito como valor calculado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Java 27 (JEP 531):&lt;/strong&gt; saíram &lt;code&gt;isInitialized()&lt;/code&gt; e &lt;code&gt;orElse(...)&lt;/code&gt;, e entrou &lt;code&gt;Set.&lt;wbr&gt;ofLazy(...)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A JEP deixa claro que o ganho de constant folding depende de a JVM confiar em campos &lt;code&gt;final&lt;/code&gt;. Campos &lt;code&gt;static final&lt;/code&gt; já são confiáveis. A maioria dos campos &lt;code&gt;final&lt;/code&gt; de instância ainda pode ser alterada por reflexão, e a JEP cita a intenção de restringir isso no longo prazo, caminho que começou com a &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#muta%C3%A7%C3%A3o-de-campos-final-por-reflex%C3%A3o-passa-a-emitir-aviso&quot;&gt;JEP 500&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;api-pem&quot;&gt;API PEM&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 25 (preview, &lt;a href=&quot;https://openjdk.org/jeps/470&quot;&gt;JEP 470&lt;/a&gt;) → Java 26 (2ª preview, &lt;a href=&quot;https://openjdk.org/jeps/524&quot;&gt;JEP 524&lt;/a&gt;) → Java 27 (3ª preview, &lt;a href=&quot;https://openjdk.org/jeps/538&quot;&gt;JEP 538&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A primeira versão está em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#codifica%C3%A7%C3%A3o-pem-de-objetos-criptogr%C3%A1ficos&quot;&gt;Codificação PEM de objetos criptográficos no post do Java 25&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O problema.&lt;/strong&gt; PEM é o formato de texto com &lt;code&gt;-----BEGIN ...-----&lt;/code&gt; usado para chaves, certificados e CRLs. Até aqui, o JDK não tinha uma API para ler e escrever esse formato: era preciso tirar cabeçalhos e decodificar Base64 à mão, ou recorrer a bibliotecas como o Bouncy Castle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Como funciona.&lt;/strong&gt; &lt;code&gt;PEMEncoder&lt;/code&gt; e &lt;code&gt;PEMDecoder&lt;/code&gt; (em &lt;code&gt;java.&lt;wbr&gt;security&lt;/code&gt;) são imutáveis, thread-safe e reutilizáveis. Eles convertem objetos que implementam a interface selada &lt;code&gt;BinaryEncodable&lt;/code&gt;: chaves assimétricas, &lt;code&gt;KeyPair&lt;/code&gt;, &lt;code&gt;X509Certificate&lt;/code&gt;, &lt;code&gt;X509CRL&lt;/code&gt;, &lt;code&gt;EncryptedPrivateKeyInfo&lt;/code&gt;, as key specs PKCS#8 e X.509 e a classe genérica &lt;code&gt;PEM&lt;/code&gt;, que cobre tipos sem API própria, como requisições de certificado PKCS#10.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:35&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ChavesPem.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;KeyPair&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;KeyPairGenerator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PEMDecoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PEMEncoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PrivateKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PublicKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;interfaces&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ECPrivateKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;interfaces&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ECPublicKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;ChavesPem&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;KeyPair&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; par &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; KeyPairGenerator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getInstance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;EC&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;generateKeyPair&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; senha &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;troque-esta-senha&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toCharArray&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Codificação: encoders são imutáveis e reutilizáveis&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PEMEncoder&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; encoder &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; PEMEncoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; publicaPem &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; encoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;encodeToString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;par&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getPublic&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; privadaPem &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; encoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;withEncryption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;senha&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;encodeToString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;par&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getPrivate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;publicaPem&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;lines&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;findFirst&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;orElseThrow&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// -----BEGIN PUBLIC KEY-----&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;privadaPem&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;lines&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;findFirst&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;orElseThrow&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// -----BEGIN ENCRYPTED PRIVATE KEY-----&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Decodificação com o tipo esperado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PEMDecoder&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; decoder &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; PEMDecoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ECPublicKey&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; publica &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; decoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;decode&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;publicaPem&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ECPublicKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ECPrivateKey&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; privada &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; decoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;withDecryption&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;senha&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;decode&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;privadaPem&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ECPrivateKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;publica&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getAlgorithm&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt; / &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; privada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getAlgorithm&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// EC / EC&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Ou sem saber o tipo de antemão, com pattern matching&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;decoder&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;decode&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;publicaPem&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PublicKey&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pk &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;chave pública &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pk&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getFormat&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// chave pública X.509&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PrivateKey&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sk &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;chave privada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;outro objeto PEM&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para rodar: &lt;code&gt;java --enable-preview --source 27 ChavesPem.&lt;wbr&gt;java&lt;/code&gt;. O código é o mesmo no Java 26, onde a interface ainda se chamava &lt;code&gt;DEREncodable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;default&lt;/code&gt; é obrigatório no &lt;code&gt;switch&lt;/code&gt; porque o &lt;code&gt;decode&lt;/code&gt; pode devolver outros tipos, como &lt;code&gt;KeyPair&lt;/code&gt;, &lt;code&gt;X509Certificate&lt;/code&gt; ou &lt;code&gt;PEM&lt;/code&gt;. Mesmo um &lt;code&gt;switch&lt;/code&gt; que liste todos os tipos públicos precisaria dele: a lista de subtipos de &lt;code&gt;BinaryEncodable&lt;/code&gt; não é exaustiva, o que, segundo o &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/security/BinaryEncodable.java&quot;&gt;Javadoc de &lt;code&gt;BinaryEncodable&lt;/code&gt;&lt;/a&gt;, permite ampliá-la no futuro sem quebrar código existente.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;O que mudou no caminho.&lt;/strong&gt; No Java 26, &lt;code&gt;PEMRecord&lt;/code&gt; virou &lt;code&gt;PEM&lt;/code&gt;, os métodos &lt;code&gt;encryptKey&lt;/code&gt; de &lt;code&gt;EncryptedPrivateKeyInfo&lt;/code&gt; viraram &lt;code&gt;encrypt&lt;/code&gt;, e encoder e decoder passaram a cifrar e decifrar &lt;code&gt;KeyPair&lt;/code&gt; e &lt;code&gt;PKCS8EncodedKeySpec&lt;/code&gt;. No Java 27, &lt;code&gt;DEREncodable&lt;/code&gt; virou &lt;code&gt;BinaryEncodable&lt;/code&gt;, &lt;code&gt;PEM&lt;/code&gt; deixou de ser record e virou classe comum, &lt;code&gt;PEMDecoder.&lt;wbr&gt;withFactory&lt;/code&gt; virou &lt;code&gt;withFactoriesOf&lt;/code&gt;, e entrou a exceção não verificada &lt;code&gt;javax.&lt;wbr&gt;crypto.&lt;wbr&gt;CryptoException&lt;/code&gt;. A &lt;a href=&quot;https://openjdk.org/jeps/542&quot;&gt;JEP 542&lt;/a&gt;, já concluída para o Java 28, finaliza a API &lt;strong&gt;sem outras mudanças&lt;/strong&gt;. Ou seja: o código escrito para o 27 deve funcionar no 28 sem &lt;code&gt;--enable-preview&lt;/code&gt;, e é a partir dali que vale trocar o parsing manual de PEM pela API em código de produção.&lt;/p&gt;
&lt;h3 id=&quot;vector-api&quot;&gt;Vector API&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chegou em:&lt;/strong&gt; Java 25 (10ª incubadora, &lt;a href=&quot;https://openjdk.org/jeps/508&quot;&gt;JEP 508&lt;/a&gt;) → Java 26 (11ª incubadora, &lt;a href=&quot;https://openjdk.org/jeps/529&quot;&gt;JEP 529&lt;/a&gt;) → Java 27 (12ª incubadora, &lt;a href=&quot;https://openjdk.org/jeps/537&quot;&gt;JEP 537&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;A Vector API (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#vector-api&quot;&gt;Vector API no post do Java 25&lt;/a&gt;) expressa cálculos vetoriais que o JIT compila para instruções SIMD da CPU, que aplicam a mesma operação a vários valores de uma vez. Nas duas versões ela voltou sem mudança relevante de API; no 27, só a biblioteca SLEEF usada em ARM e RISC-V foi atualizada. Pelas JEPs, ela fica na incubadora até que os recursos necessários do Project Valhalla cheguem como preview. Em 16/09/2026, o primeiro preview de Value Objects (&lt;a href=&quot;https://openjdk.org/jeps/401&quot;&gt;JEP 401&lt;/a&gt;), do Valhalla, já tinha alvo no Java 28.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:29&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;SomaVetorial.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jdk&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;incubator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FloatVector&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;jdk&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;incubator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VectorSpecies&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;SomaVetorial&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VectorSpecies&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ESPECIE &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; FloatVector&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;SPECIES_PREFERRED&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// c[i] = -(a[i]² + b[i]²), processando várias posições por instrução da CPU&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; calcular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; limite &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ESPECIE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;loopBound&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; limite&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ESPECIE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; va &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; FloatVector&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fromArray&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ESPECIE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; vb &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; FloatVector&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fromArray&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ESPECIE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;va&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mul&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;va&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;vb&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;mul&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;vb&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;neg&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;intoArray&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;           &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// sobra que não completa um vetor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;])&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1.0f&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; c &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;calcular&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Arrays&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// [-82.0, -68.0, -58.0, -52.0, -50.0, -52.0, -58.0, -68.0, -82.0]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para rodar: &lt;code&gt;java --add-modules jdk.&lt;wbr&gt;incubator.&lt;wbr&gt;vector SomaVetorial.&lt;wbr&gt;java&lt;/code&gt;. Sem o &lt;code&gt;--add-modules&lt;/code&gt;, o pacote não fica visível e a compilação falha. Com ele, a JVM também imprime &lt;code&gt;WARNING: Using incubator modules: jdk.&lt;wbr&gt;incubator.&lt;wbr&gt;vector&lt;/code&gt; antes da saída.&lt;/p&gt;
&lt;h2 id=&quot;o-que-observar-vindo-do-java-25&quot;&gt;O que observar vindo do Java 25&lt;/h2&gt;
&lt;p&gt;Mudanças confirmadas no 26 e no 27 que podem quebrar build, testes ou comportamento em produção:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Recompilar tudo o que usa preview.&lt;/strong&gt; Pela &lt;a href=&quot;https://openjdk.org/jeps/12&quot;&gt;JEP 12&lt;/a&gt;, uma JVM não carrega classes que dependem dos previews de outra versão. E as APIs mudaram entre versões: exceções do &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#structured-concurrency&quot;&gt;&lt;code&gt;StructuredTaskScope&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;FailedException&lt;/code&gt; → &lt;code&gt;ExecutionException&lt;/code&gt;), &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#lazy-constants&quot;&gt;&lt;code&gt;StableValue&lt;/code&gt; → &lt;code&gt;LazyConstant&lt;/code&gt;&lt;/a&gt; sem &lt;code&gt;isInitialized&lt;/code&gt;/&lt;code&gt;orElse&lt;/code&gt;, &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#api-pem&quot;&gt;&lt;code&gt;DEREncodable&lt;/code&gt; → &lt;code&gt;BinaryEncodable&lt;/code&gt;&lt;/a&gt;. Com a &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#tipos-primitivos-em-patterns-instanceof-e-switch&quot;&gt;dominância mais rígida&lt;/a&gt; em &lt;code&gt;switch&lt;/code&gt; com primitivos, alguns &lt;code&gt;switch&lt;/code&gt; que compilavam deixam de compilar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avisos de &lt;code&gt;final&lt;/code&gt; alterado por reflexão&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/jeps/500&quot;&gt;JEP 500&lt;/a&gt;, &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#muta%C3%A7%C3%A3o-de-campos-final-por-reflex%C3%A3o-passa-a-emitir-aviso&quot;&gt;detalhes&lt;/a&gt;). Procure os &lt;code&gt;WARNING: Final field ...&lt;/code&gt; nos logs e rode os testes com &lt;code&gt;--illegal-final-field-mutation=deny&lt;/code&gt;. Frameworks de injeção, mocks e serialização são os suspeitos de sempre.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coletor em containers pequenos&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/jeps/523&quot;&gt;JEP 523&lt;/a&gt;, &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#g1-como-coletor-padr%C3%A3o-em-qualquer-ambiente&quot;&gt;detalhes&lt;/a&gt;). Com 1 CPU ou menos de 1792 MB, o padrão passa de Serial para G1. Meça memória e latência e, se preciso, fixe &lt;code&gt;-XX:+UseSerialGC&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Layout de objeto&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/jeps/534&quot;&gt;JEP 534&lt;/a&gt;, &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#compact-object-headers-ligados-por-padr%C3%A3o&quot;&gt;detalhes&lt;/a&gt;). Os compact object headers vêm ligados. Se algo depender do layout antigo, &lt;code&gt;-XX:-UseCompactObjectHeaders&lt;/code&gt; desliga.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flags e dimensionamento de heap.&lt;/strong&gt; No 26, sem &lt;code&gt;-Xms&lt;/code&gt;, o heap inicial passa a ser o mínimo possível; quem dependia do padrão antigo pode fixar &lt;code&gt;-Xms&lt;/code&gt; ou &lt;code&gt;-XX:InitialRAMPercentage=1.5625&lt;/code&gt; (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas do 26&lt;/a&gt;). No 27, &lt;code&gt;-noverify&lt;/code&gt;/&lt;code&gt;-Xverify:none&lt;/code&gt;, &lt;code&gt;-noclassgc&lt;/code&gt;, &lt;code&gt;-verifyremote&lt;/code&gt; e &lt;code&gt;-XX:+UseGraalJIT&lt;/code&gt; foram removidas, &lt;code&gt;UseCompressedClassPointers&lt;/code&gt; ficou obsoleta, os padrões de &lt;code&gt;Min/MaxHeapFreeRatio&lt;/code&gt; no G1 mudaram e &lt;code&gt;InitiatingHeapOccupancyPercent&lt;/code&gt; virou &lt;code&gt;G1IHOP&lt;/code&gt; (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;). Revise scripts de startup, Dockerfiles e &lt;code&gt;JAVA_TOOL_OPTIONS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APIs removidas.&lt;/strong&gt; &lt;code&gt;Thread.&lt;wbr&gt;stop()&lt;/code&gt;, a Applet API e &lt;code&gt;ThreadPoolExecutor.&lt;wbr&gt;finalize()&lt;/code&gt;. No último caso, quem sobrescrevia &lt;code&gt;finalize()&lt;/code&gt; chamando &lt;code&gt;super.&lt;wbr&gt;finalize()&lt;/code&gt; passa a chamar &lt;code&gt;Object.&lt;wbr&gt;finalize()&lt;/code&gt;, que declara &lt;code&gt;throws Throwable&lt;/code&gt;, e o código pode deixar de compilar (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rede e HTTP.&lt;/strong&gt; No 26, o timeout de &lt;code&gt;HttpRequest.&lt;wbr&gt;Builder.&lt;wbr&gt;timeout&lt;/code&gt; passou a cobrir também a leitura do corpo da resposta, e os atributos de &lt;code&gt;HttpContext&lt;/code&gt; deixaram de ser compartilhados com cada &lt;code&gt;HttpExchange&lt;/code&gt; no servidor embutido (a propriedade &lt;code&gt;jdk.&lt;wbr&gt;httpserver.&lt;wbr&gt;attributes&lt;/code&gt; restaura o comportamento antigo). No 27, o &lt;code&gt;HttpServer&lt;/code&gt; passou de casamento por prefixo de string para prefixo de caminho: o contexto &lt;code&gt;/foo&lt;/code&gt; não casa mais com &lt;code&gt;/foobar&lt;/code&gt;, e a propriedade &lt;code&gt;sun.&lt;wbr&gt;net.&lt;wbr&gt;httpserver.&lt;wbr&gt;pathMatcher&lt;/code&gt; restaura o comportamento antigo (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas do 26&lt;/a&gt;, &lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TLS e criptografia no 27.&lt;/strong&gt; &lt;code&gt;X25519MLKEM768&lt;/code&gt; vira o grupo preferido. &lt;code&gt;ffdhe6144&lt;/code&gt;/&lt;code&gt;ffdhe8192&lt;/code&gt; saem da lista padrão. A derivação de chave do TLS 1.3 passa a usar chaves &lt;code&gt;Generic&lt;/code&gt;, e providers JCE que não as suportam podem falhar no handshake (a propriedade &lt;code&gt;jdk.&lt;wbr&gt;tls.&lt;wbr&gt;t13KeyDerivationAlgorithm=TlsPremasterSecret&lt;/code&gt; restaura o comportamento anterior). Chaves privadas ML-KEM e ML-DSA codificadas no 27 (formato &lt;code&gt;seed&lt;/code&gt;) não são aceitas por versões anteriores por padrão (&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saídas e exceções que mudaram.&lt;/strong&gt; No 26, &lt;code&gt;DecimalFormat&lt;/code&gt; passou a usar o algoritmo de &lt;code&gt;Double.&lt;wbr&gt;toString&lt;/code&gt; (&lt;code&gt;-Djdk.&lt;wbr&gt;compat.&lt;wbr&gt;DecimalFormat=true&lt;/code&gt; restaura o antigo). No 27, o thread dump em JSON usa números nos IDs, e &lt;code&gt;ZipOutputStream.&lt;wbr&gt;putNextEntry&lt;/code&gt; lança &lt;code&gt;ZipException&lt;/code&gt; em vez de &lt;code&gt;IllegalArgumentException&lt;/code&gt; para nomes que não podem ser codificados (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas do 26&lt;/a&gt;, &lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dados de locale, TLS e compilação.&lt;/strong&gt; No 26, os dados de locale passaram ao CLDR 48 e, no 27, ao CLDR 48.2, com mudanças em formatos de data, hora e número (por exemplo, o separador de milhar suíço); testes que comparam texto formatado podem falhar. Também no 26, conexões RMI sobre TLS passaram a verificar por padrão se o certificado do servidor corresponde ao nome do host (&lt;code&gt;jdk.&lt;wbr&gt;rmi.&lt;wbr&gt;ssl.&lt;wbr&gt;client.&lt;wbr&gt;enableEndpointIdentification=false&lt;/code&gt; desliga), e o &lt;code&gt;KeyManager&lt;/code&gt; &lt;code&gt;SunX509&lt;/code&gt; passou a checar os certificados locais contra as restrições de algoritmos (&lt;code&gt;jdk.&lt;wbr&gt;tls.&lt;wbr&gt;SunX509KeyManager.&lt;wbr&gt;certChecking=false&lt;/code&gt; restaura o comportamento antigo). No 27, o &lt;code&gt;javac&lt;/code&gt; passou a rejeitar anotações &lt;code&gt;TYPE_USE&lt;/code&gt; em variáveis com tipo inferido, como as declaradas com &lt;code&gt;var&lt;/code&gt;, inclusive parâmetros de lambda (&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;notas do 26&lt;/a&gt;, &lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;notas do 27&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;todas-as-jeps-versão-a-versão&quot;&gt;Todas as JEPs, versão a versão&lt;/h2&gt;
&lt;p&gt;Listas conferidas nas páginas oficiais de cada release no OpenJDK; os títulos seguem as páginas das JEPs. Tipos: &lt;strong&gt;Final&lt;/strong&gt; (recurso permanente ou mudança de implementação), &lt;strong&gt;Preview&lt;/strong&gt;, &lt;strong&gt;Incubadora&lt;/strong&gt;, &lt;strong&gt;Experimental&lt;/strong&gt;, &lt;strong&gt;Depreciação&lt;/strong&gt;, &lt;strong&gt;Remoção&lt;/strong&gt;, &lt;strong&gt;Plataforma&lt;/strong&gt; (port para sistema operacional ou arquitetura) e &lt;strong&gt;Interno&lt;/strong&gt; (mudança no desenvolvimento do próprio OpenJDK, sem efeito para quem usa o JDK).&lt;/p&gt;
&lt;h3 id=&quot;java-26&quot;&gt;Java 26&lt;/h3&gt;
&lt;p&gt;Lançado em 17 de março de 2026, com 10 JEPs (&lt;a href=&quot;https://openjdk.org/projects/jdk/26/&quot;&gt;JDK 26&lt;/a&gt;).&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Ver as 10 JEPs do Java 26&lt;/summary&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: JEP, Título, Tipo&quot;&gt;



























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;JEP&lt;/th&gt;&lt;th&gt;Título&lt;/th&gt;&lt;th&gt;Tipo&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/500&quot;&gt;500&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Prepare to Make Final Mean Final&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/504&quot;&gt;504&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Remove the Applet API&lt;/td&gt;&lt;td&gt;Remoção&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/516&quot;&gt;516&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Ahead-of-Time Object Caching with Any GC&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/517&quot;&gt;517&lt;/a&gt;&lt;/td&gt;&lt;td&gt;HTTP/3 for the HTTP Client API&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/522&quot;&gt;522&lt;/a&gt;&lt;/td&gt;&lt;td&gt;G1 GC: Improve Throughput by Reducing Synchronization&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/524&quot;&gt;524&lt;/a&gt;&lt;/td&gt;&lt;td&gt;PEM Encodings of Cryptographic Objects (Second Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/525&quot;&gt;525&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Structured Concurrency (Sixth Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/526&quot;&gt;526&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Lazy Constants (Second Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/529&quot;&gt;529&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Vector API (Eleventh Incubator)&lt;/td&gt;&lt;td&gt;Incubadora&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/530&quot;&gt;530&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Primitive Types in Patterns, instanceof, and switch (Fourth Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h3 id=&quot;java-27&quot;&gt;Java 27&lt;/h3&gt;
&lt;p&gt;Lançado em 15 de setembro de 2026, com 9 JEPs (&lt;a href=&quot;https://openjdk.org/projects/jdk/27/&quot;&gt;JDK 27&lt;/a&gt;).&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Ver as 9 JEPs do Java 27&lt;/summary&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: JEP, Título, Tipo&quot;&gt;






















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;JEP&lt;/th&gt;&lt;th&gt;Título&lt;/th&gt;&lt;th&gt;Tipo&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/523&quot;&gt;523&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Make G1 the Default Garbage Collector in All Environments&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/527&quot;&gt;527&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Post-Quantum Hybrid Key Exchange for TLS 1.3&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/531&quot;&gt;531&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Lazy Constants (Third Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/532&quot;&gt;532&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Primitive Types in Patterns, instanceof, and switch (Fifth Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/533&quot;&gt;533&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Structured Concurrency (Seventh Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/534&quot;&gt;534&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Compact Object Headers by Default&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/536&quot;&gt;536&lt;/a&gt;&lt;/td&gt;&lt;td&gt;JFR In-Process Data Redaction&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/537&quot;&gt;537&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Vector API (Twelfth Incubator)&lt;/td&gt;&lt;td&gt;Incubadora&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/538&quot;&gt;538&lt;/a&gt;&lt;/td&gt;&lt;td&gt;PEM Encodings of Cryptographic Objects (Third Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h3 id=&quot;java-28&quot;&gt;Java 28&lt;/h3&gt;
&lt;p&gt;Em desenvolvimento. A &lt;a href=&quot;https://openjdk.org/projects/jdk/28/&quot;&gt;página do JDK 28&lt;/a&gt; ainda não publicou o cronograma, e o roadmap da Oracle prevê o lançamento para março de 2027. Na última atualização da página (27/08/2026), estas eram as JEPs com alvo no 28; a coluna Situação mostra o status de cada JEP em 16/09/2026. “Com alvo” significa que a JEP foi aceita para o 28; “integrada”, que o código já entrou no repositório do 28; “concluída”, que além disso a JEP foi encerrada como entregue.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Ver as 6 JEPs do Java 28&lt;/summary&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: JEP, Título, Tipo, Situação&quot;&gt;














































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;JEP&lt;/th&gt;&lt;th&gt;Título&lt;/th&gt;&lt;th&gt;Tipo&lt;/th&gt;&lt;th&gt;Situação&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/401&quot;&gt;401&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Value Objects (Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;td&gt;Integrada ao 28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/535&quot;&gt;535&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Shenandoah GC: Generational Mode by Default&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;td&gt;Com alvo no 28, ainda não integrada&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/539&quot;&gt;539&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Strict Field Initialization in the JVM (Preview)&lt;/td&gt;&lt;td&gt;Preview&lt;/td&gt;&lt;td&gt;Integrada ao 28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/540&quot;&gt;540&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Simple JSON API (Incubator)&lt;/td&gt;&lt;td&gt;Incubadora&lt;/td&gt;&lt;td&gt;Integrada ao 28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/541&quot;&gt;541&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Deprecate the macOS/x64 Port for Removal&lt;/td&gt;&lt;td&gt;Depreciação&lt;/td&gt;&lt;td&gt;Concluída no 28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://openjdk.org/jeps/542&quot;&gt;542&lt;/a&gt;&lt;/td&gt;&lt;td&gt;PEM Encodings of Cryptographic Objects&lt;/td&gt;&lt;td&gt;Final&lt;/td&gt;&lt;td&gt;Concluída no 28&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;Em resumo: &lt;strong&gt;Value Objects&lt;/strong&gt; (Project Valhalla) introduz, em preview, objetos imutáveis e sem identidade, distinguidos só pelos valores dos campos, que a JVM pode representar de forma mais eficiente. &lt;strong&gt;Strict Field Initialization&lt;/strong&gt; é um recurso de VM em preview, voltado a compiladores que geram class files, no qual o campo precisa ser inicializado antes de qualquer leitura, de modo que &lt;code&gt;0&lt;/code&gt; e &lt;code&gt;null&lt;/code&gt; nunca são observados. A &lt;strong&gt;Simple JSON API&lt;/strong&gt; (&lt;code&gt;jdk.&lt;wbr&gt;incubator.&lt;wbr&gt;json&lt;/code&gt;) faz parsing e geração de JSON sem biblioteca externa. No &lt;strong&gt;Shenandoah&lt;/strong&gt;, o modo geracional vira padrão e o não geracional (&lt;code&gt;ShenandoahGCMode=satb&lt;/code&gt;) é depreciado. A &lt;strong&gt;API PEM&lt;/strong&gt; vira final.&lt;/p&gt;
&lt;p&gt;Fora da lista, a &lt;a href=&quot;https://openjdk.org/jeps/543&quot;&gt;JEP 543&lt;/a&gt; (candidata, sem versão definida) propõe finalizar Structured Concurrency no Java 28. Nada disso está garantido até o Java 28 sair, e este post será atualizado quando isso acontecer.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;p&gt;Consultadas em 16/09/2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cronograma e suporte&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/java-se-support-roadmap.html&quot;&gt;Oracle Java SE Support Roadmap&lt;/a&gt;: Java 29 como próxima LTS prevista (setembro de 2027); 26, 27 e 28 não LTS; prazos de Premier Support&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openjdk.org/projects/jdk/26/&quot;&gt;JDK 26, página do projeto&lt;/a&gt;: JEPs e GA em 17/03/2026&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openjdk.org/projects/jdk/27/&quot;&gt;JDK 27, página do projeto&lt;/a&gt;: JEPs, cronograma e GA em 15/09/2026&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openjdk.org/projects/jdk/28/&quot;&gt;JDK 28, página do projeto&lt;/a&gt;: JEPs com alvo no 28&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openjdk.org/jeps/0&quot;&gt;JEP 0 — JEP Index&lt;/a&gt;: status das JEPs em andamento&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mail.openjdk.org/archives/list/announce@openjdk.org/thread/ORGGLMN75HFEWP7YL3ZLGHLYHVIBJDYT/&quot;&gt;Anúncio de GA do JDK 27 (announce@openjdk.org)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mail.openjdk.org/archives/list/jdk-dev@openjdk.org/thread/2MXXXBJKTJXQD25Q4XGGINKYA33T7D5I/&quot;&gt;Anúncio de GA do JDK 26 (jdk-dev@openjdk.org)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Notas de release&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://jdk.java.net/27/release-notes&quot;&gt;JDK 27 Release Notes (jdk.java.net)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/javase/26-relnote-issues.html&quot;&gt;JDK 26 Release Notes (Oracle)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.openjdk.org/browse/JDK-8369238&quot;&gt;JDK-8369238&lt;/a&gt;: virtual threads e inicialização de classes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;JEPs&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anteriores ao Java 26: &lt;a href=&quot;https://openjdk.org/jeps/243&quot;&gt;JEP 243&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/248&quot;&gt;JEP 248&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/289&quot;&gt;JEP 289&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/321&quot;&gt;JEP 321&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/398&quot;&gt;JEP 398&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/450&quot;&gt;JEP 450&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/483&quot;&gt;JEP 483&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/470&quot;&gt;JEP 470&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/502&quot;&gt;JEP 502&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/505&quot;&gt;JEP 505&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/507&quot;&gt;JEP 507&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/508&quot;&gt;JEP 508&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/514&quot;&gt;JEP 514&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/519&quot;&gt;JEP 519&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Java 26: &lt;a href=&quot;https://openjdk.org/jeps/500&quot;&gt;JEP 500&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/504&quot;&gt;JEP 504&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/516&quot;&gt;JEP 516&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/517&quot;&gt;JEP 517&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/522&quot;&gt;JEP 522&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/524&quot;&gt;JEP 524&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/525&quot;&gt;JEP 525&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/526&quot;&gt;JEP 526&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/529&quot;&gt;JEP 529&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/530&quot;&gt;JEP 530&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Java 27: &lt;a href=&quot;https://openjdk.org/jeps/523&quot;&gt;JEP 523&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/527&quot;&gt;JEP 527&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/531&quot;&gt;JEP 531&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/532&quot;&gt;JEP 532&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/533&quot;&gt;JEP 533&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/534&quot;&gt;JEP 534&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/536&quot;&gt;JEP 536&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/537&quot;&gt;JEP 537&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/538&quot;&gt;JEP 538&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Java 28 (com alvo ou candidata): &lt;a href=&quot;https://openjdk.org/jeps/401&quot;&gt;JEP 401&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/535&quot;&gt;JEP 535&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/539&quot;&gt;JEP 539&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/540&quot;&gt;JEP 540&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/541&quot;&gt;JEP 541&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/542&quot;&gt;JEP 542&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/543&quot;&gt;JEP 543&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Processo: &lt;a href=&quot;https://openjdk.org/jeps/11&quot;&gt;JEP 11 — Incubator Modules&lt;/a&gt; e &lt;a href=&quot;https://openjdk.org/jeps/12&quot;&gt;JEP 12 — Preview Features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Código-fonte do JDK 27 (tag &lt;code&gt;jdk-27-ga&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java&quot;&gt;StructuredTaskScope.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/lang/LazyConstant.java&quot;&gt;LazyConstant.java&lt;/a&gt; e &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/util/Set.java&quot;&gt;Set.java (&lt;code&gt;Set.&lt;wbr&gt;ofLazy&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/security/PEMEncoder.java&quot;&gt;PEMEncoder.java&lt;/a&gt;, &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/security/PEMDecoder.java&quot;&gt;PEMDecoder.java&lt;/a&gt;, &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/java/security/BinaryEncodable.java&quot;&gt;BinaryEncodable.java&lt;/a&gt; e &lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.base/share/classes/javax/crypto/CryptoException.java&quot;&gt;CryptoException.java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/blob/jdk-27-ga/src/java.net.http/share/classes/java/net/http/HttpOption.java&quot;&gt;HttpOption.java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Atualizações do Java</category><category>LTS</category><category>JVM</category><category>Concorrência</category><category>Criptografia</category></item><item><title>Bloqueio otimista e pessimista — como funcionam e quando usar cada um</title><link>https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/</guid><description>Como impedir que gravações simultâneas se atropelem: coluna de versão ou trava da linha. SQL testado no PostgreSQL, Spring Data JPA, NOWAIT e SKIP LOCKED, deadlock, isolamento e o UPDATE condicional.</description><pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Quando duas requisições leem a mesma linha, calculam um valor novo e gravam, uma delas pode apagar o trabalho da outra sem erro nenhum. Este post mostra as duas formas clássicas de impedir isso, o &lt;strong&gt;bloqueio otimista&lt;/strong&gt; (detectar o conflito) e o &lt;strong&gt;bloqueio pessimista&lt;/strong&gt; (evitar o conflito), com SQL testado no PostgreSQL e o equivalente em Spring Data JPA. Depois, o terceiro caminho que muitas vezes dispensa ambos (o UPDATE condicional), o papel dos níveis de isolamento, um critério de escolha e as perguntas que eu faço antes de decidir.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;O tema aparece de raspão no artigo sobre &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;chave de idempotência&lt;/a&gt;, como alternativa à restrição única. Aqui ele ganha o espaço que merece.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-o-problema-que-os-dois-resolvem&quot;&gt;1. O problema que os dois resolvem&lt;/h2&gt;
&lt;p&gt;Os dois existem para o mesmo defeito, que tem nome: &lt;strong&gt;lost update&lt;/strong&gt;, a atualização perdida.&lt;/p&gt;
&lt;p&gt;Dois clientes leem a mesma linha, cada um calcula um valor novo a partir do que leu, e os dois gravam. A segunda gravação sobrescreve a primeira, e a primeira desaparece sem erro nenhum. O saldo fica errado e o log está limpo. Aparece em contador de estoque, em saldo, em qualquer campo calculado a partir do valor lido.&lt;/p&gt;
&lt;p&gt;É a mesma família do problema da &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;cobrança duplicada no retry&lt;/a&gt;: ler, decidir e gravar como operações separadas, com uma janela no meio. Lá, a solução foi uma restrição única, que funciona quando a decisão cabe numa chave. Aqui o caso é outro: a decisão depende do &lt;strong&gt;valor lido&lt;/strong&gt;, e não existe chave que expresse isso.&lt;/p&gt;
&lt;p&gt;A diferença entre os dois bloqueios cabe numa frase, e é assim que o catálogo de padrões do Martin Fowler os descreve: &lt;strong&gt;bloqueio otimista é detecção de conflito; bloqueio pessimista é prevenção de conflito.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Uma boa analogia é o controle de versão&lt;/strong&gt;, que você usa todo dia. Duas pessoas precisam mexer no mesmo arquivo.&lt;/p&gt;
&lt;p&gt;No jeito otimista, o do Git (e antes dele o do CVS e do Subversion), as duas copiam o arquivo e editam à vontade, sem pedir permissão a ninguém. Quem termina primeiro envia sem problema. Quando a segunda tenta enviar, o sistema compara e recusa: &lt;em&gt;isto aqui mudou desde que você copiou.&lt;/em&gt; Ela junta as mudanças e envia de novo.&lt;/p&gt;
&lt;p&gt;No jeito pessimista, o de sistemas mais antigos no modelo “trava, modifica, destrava”, quem chega primeiro trava o arquivo. A segunda pessoa simplesmente não consegue editar até a primeira liberar. Conflito nunca acontece, porque nunca há duas edições ao mesmo tempo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A frase carrega três consequências&lt;/strong&gt;, que valem mais do que ela:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Onde o custo cai.&lt;/strong&gt; No otimista, o caso normal é de graça: ninguém espera por ninguém, e só se paga quando o conflito de fato acontece. No pessimista, o custo é cobrado sempre: mesmo quando ninguém mais ia mexer naquela linha, o segundo espera do mesmo jeito. Um cobra por conflito; o outro cobra por acesso.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quem lida com a falha.&lt;/strong&gt; &lt;strong&gt;Detecção produz erro, e erro precisa de dono: alguém relê, refaz e tenta outra vez. Prevenção produz espera.&lt;/strong&gt; Por isso o pessimista parece mais simples no código: no caso normal, não há caminho de exceção para escrever. O preço aparece no comportamento sob carga.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O que acontece com o trabalho já feito.&lt;/strong&gt; No otimista, a segunda pessoa trabalhou e pode ter que jogar tudo fora. No pessimista, ela nem começou: ficou parada. &lt;strong&gt;Quando o trabalho é caro ou demorado, jogar fora dói; quando é barato, esperar dói mais.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A aposta de cada um está no próprio nome. O otimista aposta que conflito é raro; se estiver certo, você ganha concorrência de graça. O pessimista aposta que conflito é provável; se estiver certo, você evita um monte de trabalho perdido. &lt;strong&gt;Escolher entre os dois é uma aposta sobre a frequência de conflito na sua carga&lt;/strong&gt;, e isso se mede, não se escolhe por gosto.&lt;/p&gt;
&lt;h2 id=&quot;2-bloqueio-otimista&quot;&gt;2. Bloqueio otimista&lt;/h2&gt;
&lt;p&gt;A aposta é que conflito é raro. Ninguém trava nada; todo mundo lê e trabalha à vontade. Na hora de gravar, a escrita carrega a pergunta junto: &lt;em&gt;o dado ainda está como eu li?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A forma de fazer essa pergunta é uma &lt;strong&gt;coluna de versão&lt;/strong&gt;, um número inteiro que muda a cada gravação. Todo UPDATE incrementa a versão e filtra pela versão que foi lida. Se outra transação gravou antes, o filtro não encontra a linha e o banco devolve zero linhas afetadas. Zero linhas afetadas é a detecção do conflito.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/bloqueio-otimista.svg&quot; alt=&quot;Diagrama: bloqueio otimista. A e B leem a linha com version 1; A grava primeiro e a versão vira 2; o UPDATE de B filtra por version 1, afeta zero linhas e B precisa reler e tentar de novo&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Em SQL puro&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:8&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- lido antes: saldo = 100, version = 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;90&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AND&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- UPDATE 1 -&gt; gravou&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- UPDATE 0 -&gt; alguém mudou a linha nesse meio-tempo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O ponto essencial: &lt;strong&gt;a verificação e a escrita são o mesmo comando&lt;/strong&gt;. Não existe janela entre uma e outra, e é por isso que funciona sem travar nada.&lt;/p&gt;
&lt;p&gt;Dá para usar uma coluna &lt;code&gt;updated_at&lt;/code&gt; no lugar da versão, mas um número inteiro é mais claro e não depende da precisão do relógio. A própria documentação do Hibernate diz que timestamp é uma forma menos confiável de bloqueio otimista do que número de versão.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Em Spring Data JPA&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;O Hibernate faz isso sozinho a partir de uma anotação:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:11&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Conta.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Entity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Conta&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                 &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// habilita o bloqueio otimista&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// o Hibernate cuida do incremento&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Com isso, todo UPDATE que o Hibernate gera para a entidade inclui a versão no filtro (&lt;code&gt;update conta set saldo=?, version=? where id=? and version=?&lt;/code&gt;). Se nenhuma linha for afetada, o Hibernate lança &lt;code&gt;OptimisticLockException&lt;/code&gt; (da JPA), e o Spring a entrega traduzida como &lt;code&gt;ObjectOptimisticLockingFailureException&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Como o conflito agora é um erro, alguém precisa decidir o que fazer com ele. Uma resposta comum é tentar de novo. Desde o Spring Framework 7 (Spring Boot 4), a anotação &lt;code&gt;@Retryable&lt;/code&gt; faz parte do próprio framework e é habilitada com &lt;code&gt;@EnableResilientMethods&lt;/code&gt; numa classe de configuração:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:13&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ContaService.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Retryable&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; ObjectOptimisticLockingFailureException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;maxRetries&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 1 tentativa + 2 retentativas&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;delay&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;multiplier&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;jitter&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;25&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Transactional&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; debitar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; contaId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Conta&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conta &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; repo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;findById&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;contaId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;orElseThrow&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setSaldo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getSaldo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;repo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;save&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Dois detalhes que sempre dão errado. Primeiro, o retry precisa &lt;strong&gt;reler&lt;/strong&gt; o dado: retentar com a entidade velha em mãos falha de novo, sempre. A documentação do Spring Framework fixa a ordem dos dois interceptadores, retry por fora e transação por dentro, então cada tentativa abre uma transação nova e faz um &lt;code&gt;findById&lt;/code&gt; novo. Segundo, precisa de teto: três tentativas no total, não um laço infinito. Num teste com Spring Boot 4.1, forçando uma gravação concorrente na primeira tentativa, a segunda releu o saldo já alterado e gravou normalmente.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;O projeto Spring Retry, de onde vinha o &lt;code&gt;@Retryable&lt;/code&gt; com &lt;code&gt;retryFor&lt;/code&gt; e &lt;code&gt;@Backoff&lt;/code&gt;, foi arquivado em julho de 2026 e substituído pelos recursos de resiliência do Spring Framework 7. Em Spring Boot 3, ele ainda é o caminho.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;O que costuma passar batido&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A versão funciona entre requisições diferentes&lt;/strong&gt;, separadas por minutos. Das duas técnicas de banco deste post, é a única que resolve o caso do usuário que abriu um formulário às 10h e salvou às 10h15: a transação no banco durou milissegundos, mas a versão lida às 10h continua sendo o critério. Basta a tela devolver a versão junto com os dados. É o padrão que o Fowler chama de &lt;em&gt;Optimistic Offline Lock&lt;/em&gt;; “offline” porque a proteção atravessa várias requisições, fora de uma única transação do banco. Em HTTP, a mesma ideia é o &lt;code&gt;ETag&lt;/code&gt; com &lt;code&gt;If-Match&lt;/code&gt;, que a RFC 9110 descreve justamente como proteção contra o lost update; no CouchDB, é o campo &lt;code&gt;_rev&lt;/code&gt;, que recusa com 409 a gravação feita sobre uma revisão antiga.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retry automático não serve para edição humana.&lt;/strong&gt; Retentar às cegas só faz sentido quando a aplicação sabe recalcular a partir do dado novo: um débito, um contador, um status. Quando quem editou foi uma pessoa, a resposta certa para o conflito é devolver o erro com o estado atual (&lt;code&gt;409 Conflict&lt;/code&gt;, ou &lt;code&gt;412 Precondition Failed&lt;/code&gt; quando a versão veio num &lt;code&gt;If-Match&lt;/code&gt;) e deixar que ela decida o que fazer com as duas versões. Sobrescrever em silêncio é exatamente o lost update que a versão existia para impedir.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UPDATE em massa passa por fora do &lt;code&gt;@Version&lt;/code&gt;.&lt;/strong&gt; Um &lt;code&gt;update&lt;/code&gt; em JPQL (com &lt;code&gt;@Modifying&lt;/code&gt;) ou em SQL nativo não checa nem incrementa a versão: quem escreve o comando precisa incluir o &lt;code&gt;version = version + 1&lt;/code&gt; e, se a decisão depende do valor lido, o filtro pela versão, como no SQL puro acima. A proteção só é automática para entidades gerenciadas que passam pelo &lt;code&gt;save&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-bloqueio-pessimista&quot;&gt;3. Bloqueio pessimista&lt;/h2&gt;
&lt;p&gt;A aposta é a inversa: conflito é provável, então é melhor não deixar acontecer. Quem chega primeiro trava a linha, e os outros esperam.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/bloqueio-pessimista.svg&quot; alt=&quot;Diagrama: bloqueio pessimista. A trava a linha com SELECT FOR UPDATE; B pede a mesma linha e fica esperando, sem erro; quando A faz COMMIT, B recebe a trava e lê o saldo já atualizado&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Em SQL puro&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:12&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- a partir daqui a linha está travada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- a aplicação confere o saldo e decide&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conta &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;               &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- a trava só sai aqui&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Quem pedir a mesma linha com &lt;code&gt;FOR UPDATE&lt;/code&gt; nesse meio-tempo fica esperando. Quando a primeira transação faz COMMIT, a segunda recebe a trava e lê a versão &lt;strong&gt;já atualizada&lt;/strong&gt; da linha, e não a que existia quando começou a esperar. É isso que impede o lost update.&lt;/p&gt;
&lt;p&gt;Três variações que vale conhecer no PostgreSQL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FOR UPDATE NOWAIT&lt;/code&gt;: em vez de esperar, falha na hora se a linha estiver travada (&lt;code&gt;could not obtain lock on row in relation &quot;conta&quot;&lt;/code&gt;). Bom quando esperar é pior que desistir.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FOR UPDATE SKIP LOCKED&lt;/code&gt;: pula as linhas travadas e devolve as outras. É assim que se implementa fila de trabalho em tabela, e a documentação do PostgreSQL cita exatamente esse uso: vários &lt;em&gt;workers&lt;/em&gt; pegam itens diferentes sem disputar o mesmo, sem &lt;em&gt;broker&lt;/em&gt; de mensagens. O relay do outbox em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt; funciona assim.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lock_timeout&lt;/code&gt;: parâmetro de configuração que limita quanto tempo um comando espera por uma trava (por exemplo, &lt;code&gt;SET LOCAL lock_timeout = &apos;3s&apos;&lt;/code&gt; vale só para a transação atual; estourado, o erro é &lt;code&gt;canceling statement due to lock timeout&lt;/code&gt;). O padrão é &lt;code&gt;0&lt;/code&gt;, que desliga o limite: sem configurar, a espera é indefinida.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Em Spring Data JPA&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:7&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ContaRepository.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;ContaRepository&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;JpaRepository&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Conta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Lock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;LockModeType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;PESSIMISTIC_WRITE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// no PostgreSQL: SELECT ... FOR NO KEY UPDATE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@QueryHints&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@QueryHint&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;jakarta.persistence.lock.timeout&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;3000&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Query&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;select c from Conta c where c.id = :id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Optional&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Conta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; findByIdParaAtualizar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Param&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Três cuidados com esse código:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;O SQL gerado não é exatamente &lt;code&gt;FOR UPDATE&lt;/code&gt;.&lt;/strong&gt; No PostgreSQL, o Hibernate traduz &lt;code&gt;PESSIMISTIC_WRITE&lt;/code&gt; para &lt;code&gt;FOR NO KEY UPDATE&lt;/code&gt;, uma trava um pouco mais fraca: bloqueia UPDATEs, DELETEs e outros &lt;code&gt;FOR UPDATE&lt;/code&gt; ou &lt;code&gt;FOR NO KEY UPDATE&lt;/code&gt; na linha, mas deixa passar o &lt;code&gt;FOR KEY SHARE&lt;/code&gt;, a trava mais leve de todas. Para o lost update, o efeito é o mesmo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O timeout depende da versão do Hibernate.&lt;/strong&gt; A dica &lt;code&gt;jakarta.&lt;wbr&gt;persistence.&lt;wbr&gt;lock.&lt;wbr&gt;timeout&lt;/code&gt; (em milissegundos) só funciona no PostgreSQL em versões recentes do Hibernate 7, que executam &lt;code&gt;SET LOCAL lock_timeout&lt;/code&gt; antes da consulta. Em testes contra o PostgreSQL 17, ela funcionou no Hibernate 7.2.24, 7.3.13 e 7.4.5 (os de Spring Boot 4.0.8 e 4.1.1): a espera parou em 3 segundos com erro de trava (no Spring Boot 4.1, &lt;code&gt;CannotAcquireLockException&lt;/code&gt;). No Hibernate 6.6 (Spring Boot 3.5) e em 7.1.8, 7.2.0 e 7.3.0, foi ignorada sem aviso, e a espera continuou indefinida. Confirme na sua versão com um teste, ou defina &lt;code&gt;lock_timeout&lt;/code&gt; direto no banco, que vale para qualquer versão.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A trava precisa de uma transação em volta.&lt;/strong&gt; O método de serviço que chama esse repositório deve ser &lt;code&gt;@Transactional&lt;/code&gt;. Sem transação, a JPA recusa a consulta com trava (&lt;code&gt;TransactionRequiredException&lt;/code&gt;, que o Spring entrega como &lt;code&gt;InvalidDataAccessApiUsageException&lt;/code&gt;). E a trava só faz sentido se a leitura e a gravação estiverem na mesma transação, porque ela é liberada no fim dela.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;O que costuma passar batido:&lt;/strong&gt; a trava dura até o commit. Se dentro da transação você chamar o adquirente e ele levar 800 ms, a linha fica travada por 800 ms e todo mundo que quiser aquela linha entra na fila atrás. &lt;strong&gt;Não chame serviço externo com uma trava na mão.&lt;/strong&gt; Como separar a chamada externa da gravação local sem perder nenhuma das duas é o tema do post &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;deadlock-o-risco-que-vem-junto&quot;&gt;Deadlock: o risco que vem junto&lt;/h3&gt;
&lt;p&gt;Duas transações travam as mesmas linhas em ordem invertida e ficam esperando uma pela outra para sempre. O PostgreSQL detecta o ciclo (a checagem roda depois de &lt;code&gt;deadlock_timeout&lt;/code&gt;, 1 segundo por padrão) e aborta uma das duas com &lt;code&gt;deadlock detected&lt;/code&gt;; a outra segue. Para a aplicação, é mais um erro que precisa de dono, igual ao conflito do otimista.&lt;/p&gt;
&lt;p&gt;A prevenção é simples e quase nunca feita: &lt;strong&gt;travar sempre na mesma ordem&lt;/strong&gt;. Quando a transação precisa de mais de uma linha, peça todas de uma vez, ordenadas:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id, saldo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code&gt;ORDER BY&lt;/code&gt; não é enfeite: no plano de execução, o nó que trava as linhas (&lt;code&gt;LockRows&lt;/code&gt;) fica acima do &lt;code&gt;Sort&lt;/code&gt;, então as travas são adquiridas na ordem do id, e duas transações que precisem das contas 3 e 7 nunca se cruzam. Some um &lt;code&gt;lock_timeout&lt;/code&gt; para que a espera, deadlock ou não, tenha teto.&lt;/p&gt;
&lt;p&gt;Deadlock é um risco típico do pessimista, mas não exclusivo dele: um UPDATE comum também trava a linha até o commit, então duas transações que atualizam as mesmas contas em ordem invertida podem travar mesmo sem &lt;code&gt;FOR UPDATE&lt;/code&gt;, com ou sem coluna de versão.&lt;/p&gt;
&lt;h3 id=&quot;quando-a-trava-precisa-atravessar-requisições&quot;&gt;Quando a trava precisa atravessar requisições&lt;/h3&gt;
&lt;p&gt;A trava de banco morre com a transação. Para um “só um por vez” que dura minutos, como reservar um assento enquanto a pessoa preenche o formulário ou fazer &lt;em&gt;check-out&lt;/em&gt; de um documento para edição, a trava vira um &lt;strong&gt;registro da aplicação&lt;/strong&gt;: uma linha numa tabela de travas dizendo quem está com o quê e até quando, obtida antes de começar e liberada no fim. Para que dois pedidos simultâneos não levem a trava juntos, a inserção usa a mesma restrição única do post de idempotência. O prazo de validade é obrigatório, porque o cliente pode sumir sem liberar. É o &lt;em&gt;Pessimistic Offline Lock&lt;/em&gt; do catálogo do Fowler, o par do otimista da seção anterior.&lt;/p&gt;
&lt;h2 id=&quot;4-o-update-condicional-que-muitas-vezes-dispensa-os-dois&quot;&gt;4. O UPDATE condicional, que muitas vezes dispensa os dois&lt;/h2&gt;
&lt;p&gt;Muita coisa que parece precisar de trava não precisa, porque dá para deixar o próprio banco fazer a conta:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:7&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AND&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; saldo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;RETURNING saldo;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- UPDATE 1 -&gt; debitou (e devolveu o saldo novo)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- UPDATE 0 -&gt; saldo insuficiente&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Aqui não há leitura prévia na aplicação, então não há janela e não há lost update. O UPDATE trava a linha por conta própria enquanto grava. Se dois débitos chegam juntos, o segundo espera o primeiro terminar e, no nível de isolamento padrão do PostgreSQL, &lt;strong&gt;reavalia o &lt;code&gt;WHERE&lt;/code&gt; sobre o saldo já atualizado&lt;/strong&gt;. Num teste com saldo 15 e dois débitos simultâneos de 10, um afetou uma linha e o outro afetou zero, e o saldo terminou em 5. O &lt;code&gt;RETURNING&lt;/code&gt; devolve o saldo novo no mesmo comando, sem outra consulta.&lt;/p&gt;
&lt;p&gt;Essa é a primeira pergunta a fazer antes de escolher entre otimista e pessimista: &lt;strong&gt;dá para escrever isso como um único comando?&lt;/strong&gt; Se der, nenhum dos dois é necessário. No post sobre &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/&quot;&gt;arquitetura de ledger&lt;/a&gt;, a mesma ideia aparece como &lt;em&gt;balance locking&lt;/em&gt;: condicionar a escrita ao saldo em vez de à versão.&lt;/p&gt;
&lt;h2 id=&quot;5-e-os-níveis-de-isolamento&quot;&gt;5. E os níveis de isolamento?&lt;/h2&gt;
&lt;p&gt;A outra forma de tratar concorrência é no nível da transação inteira, em vez de linha a linha. O PostgreSQL usa READ COMMITTED por padrão, e nele o padrão “leu na aplicação, calculou, gravou” &lt;strong&gt;não&lt;/strong&gt; está protegido: cada comando enxerga o que já foi confirmado, e a segunda gravação simplesmente passa por cima da primeira. Daí a necessidade de bloqueio explícito.&lt;/p&gt;
&lt;p&gt;Em REPEATABLE READ e SERIALIZABLE, o PostgreSQL impede o lost update por conta própria: quando a transação tenta gravar uma linha que outra transação alterou e confirmou depois do início dela, o comando é abortado com &lt;code&gt;could not serialize access due to concurrent update&lt;/code&gt;. Repare no que isso é: &lt;strong&gt;bloqueio otimista feito pelo banco&lt;/strong&gt;, com a mesma consequência. Detecção produz erro, e o erro continua precisando de dono: alguém relê e tenta de novo. Subir o isolamento muda quem detecta o conflito, não elimina o tratamento dele.&lt;/p&gt;
&lt;p&gt;O SERIALIZABLE vai além: pega anomalias que nenhuma trava de linha pega, como duas transações que leem um conjunto de linhas e cada uma grava numa linha diferente com base no que leu (&lt;em&gt;write skew&lt;/em&gt;). O preço é mais abortos sob disputa e mais trabalho do banco para rastrear as dependências. E, como a trava, o isolamento vive dentro de uma transação: não protege o formulário aberto às 10h e salvo às 10h15.&lt;/p&gt;
&lt;h2 id=&quot;6-como-escolher&quot;&gt;6. Como escolher&lt;/h2&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Otimista, Pessimista&quot;&gt;







































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Otimista&lt;/th&gt;&lt;th&gt;Pessimista&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Estratégia&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;detecta o conflito ao gravar&lt;/td&gt;&lt;td&gt;evita o conflito antes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Custo no caso normal&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;nenhum: ninguém espera&lt;/td&gt;&lt;td&gt;espera de quem chega depois&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Custo sob disputa&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;retentativas, que podem virar avalanche&lt;/td&gt;&lt;td&gt;fila, e risco de deadlock&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Quem trata a falha&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;a aplicação, relendo e tentando de novo&lt;/td&gt;&lt;td&gt;ninguém no caso normal; timeout e deadlock ainda viram erro&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Funciona entre requisições?&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;sim, com a versão indo e voltando&lt;/td&gt;&lt;td&gt;não com trava de banco, que só vive dentro da transação&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Onde encaixa&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;conflito raro, leitura pesada, edição por tela&lt;/td&gt;&lt;td&gt;conflito frequente, operação crítica, transação curta&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Na descrição do Fowler, o pessimista limita a concorrência do sistema, enquanto o otimista deixa várias pessoas trabalharem nos mesmos dados ao mesmo tempo. Na prática, isso leva a uma regra que funciona bem: comece otimista, que é mais simples e não cria filas. A pergunta certa não é “quando usar o otimista”, e sim &lt;strong&gt;“quando o otimista sozinho não basta”&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;O critério prático que eu uso é a taxa de disputa pela mesma linha. Cadastro de cliente, limite, parâmetro de produto, qualquer coisa que uma pessoa edita numa tela: otimista. Saldo de uma única conta em dia de pico, contador de uso de limite, qualquer linha que o sistema atualiza por conta própria muitas vezes por segundo: pessimista ou, melhor ainda, um único UPDATE condicional.&lt;/p&gt;
&lt;h3 id=&quot;quando-nenhum-dos-dois-basta-a-linha-quente&quot;&gt;Quando nenhum dos dois basta: a linha quente&lt;/h3&gt;
&lt;p&gt;Existe um caso em que a escolha não resolve: a &lt;strong&gt;linha quente&lt;/strong&gt;, uma única linha que todo mundo grava. Um contador global, o saldo da conta que recebe todos os créditos do dia, o estoque do produto em promoção. O otimista vira avalanche de retentativas, porque quase toda gravação encontra a versão mudada. O pessimista e o UPDATE condicional funcionam, mas serializam: cada gravação espera a anterior confirmar, e a vazão daquela linha fica limitada pela duração de uma transação. Não há trava que resolva isso, porque o problema não é a concorrência, é o modelo.&lt;/p&gt;
&lt;p&gt;A saída é mudar o que se grava. Em vez de atualizar o saldo, &lt;strong&gt;acrescente lançamentos&lt;/strong&gt; (uma linha por crédito, só INSERT, sem disputa) e calcule ou materialize o saldo em outro momento, que é o desenho de &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/&quot;&gt;ledger&lt;/a&gt;. Contadores podem ser divididos em várias linhas (&lt;em&gt;sharded counters&lt;/em&gt;) somadas na leitura. E quando a ordem importa, uma fila que serializa as gravações de propósito, em lote, costuma render mais do que centenas de transações disputando a mesma linha.&lt;/p&gt;
&lt;h2 id=&quot;7-cinco-perguntas-antes-de-decidir&quot;&gt;7. Cinco perguntas antes de decidir&lt;/h2&gt;
&lt;p&gt;São as perguntas que eu faço a um desenho antes de aprová-lo, e a falta de resposta costuma ser exatamente onde ele quebra em produção.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Quem trata o conflito, e o que o usuário final vê?&lt;/strong&gt; Se a aplicação sabe recalcular (débito, contador), retry com teto, e o usuário nem fica sabendo. Se quem editou foi uma pessoa, ela vê o conflito e decide; retry automático aqui é sobrescrever em silêncio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Como você percebe a avalanche de retentativas antes do cliente?&lt;/strong&gt; Contando: cada &lt;code&gt;ObjectOptimisticLockingFailureException&lt;/code&gt; e cada retry esgotado viram métrica, com alerta na taxa. Se a taxa sobe junto com a carga, a aposta do otimista estava errada para aquela linha: é hora de UPDATE condicional, de pessimista ou de repensar o modelo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Existe chamada externa dentro da trava?&lt;/strong&gt; Não pode existir. A trava envolve só a gravação local; o adquirente, o e-mail e a fila ficam fora, e o desenho para não perder nenhum dos dois lados está em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A transação trava mais de uma linha?&lt;/strong&gt; Então trava sempre na mesma ordem, com &lt;code&gt;lock_timeout&lt;/code&gt;, e com a transação mais curta que der. Deadlock não é azar: é ordem de travamento que ninguém definiu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Vamos subir para SERIALIZABLE e resolver de uma vez”?&lt;/strong&gt; Resolve a detecção, não o tratamento: a aplicação continua precisando retentar, e sob disputa aborta mais do que a coluna de versão. Vale quando o invariante atravessa várias linhas; não substitui a versão que vai e volta com o formulário.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/#apresentacao&quot;&gt;Apresentação em slides, no site&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Martin Fowler — &lt;a href=&quot;https://www.martinfowler.com/eaaCatalog/optimisticOfflineLock.html&quot;&gt;Optimistic Offline Lock&lt;/a&gt; (&lt;em&gt;Patterns of Enterprise Application Architecture&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Martin Fowler — &lt;a href=&quot;https://martinfowler.com/eaaCatalog/pessimisticOfflineLock.html&quot;&gt;Pessimistic Offline Lock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Version Control with Subversion — &lt;a href=&quot;https://svnbook.red-bean.com/en/1.7/svn.basic.version-control-basics.html&quot;&gt;Version Control Basics (lock-modify-unlock e copy-modify-merge)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/explicit-locking.html&quot;&gt;Explicit Locking (modos de trava de linha e deadlocks)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/sql-select.html&quot;&gt;SELECT: cláusula de trava (NOWAIT, SKIP LOCKED)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/sql-update.html&quot;&gt;UPDATE (cláusula RETURNING)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/runtime-config-client.html&quot;&gt;Client Connection Defaults (&lt;code&gt;lock_timeout&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/transaction-iso.html&quot;&gt;Transaction Isolation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hibernate ORM — &lt;a href=&quot;https://docs.hibernate.org/orm/current/userguide/html_single/Hibernate_User_Guide.html#locking&quot;&gt;User Guide: Locking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hibernate ORM — &lt;a href=&quot;https://github.com/hibernate/hibernate-orm/blob/7.4.5/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/PostgreSQLLockingSupport.java&quot;&gt;&lt;code&gt;PostgreSQLLockingSupport&lt;/code&gt; (aplicação do lock timeout via &lt;code&gt;SET LOCAL lock_timeout&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Data JPA — &lt;a href=&quot;https://docs.spring.io/spring-data/jpa/reference/jpa/locking.html&quot;&gt;Locking&lt;/a&gt; e &lt;a href=&quot;https://docs.spring.io/spring-data/jpa/reference/jpa/transactions.html&quot;&gt;Transactionality&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Framework — &lt;a href=&quot;https://docs.spring.io/spring-framework/reference/core/resilience.html&quot;&gt;Resilience Features (&lt;code&gt;@Retryable&lt;/code&gt;, ordem com &lt;code&gt;@Transactional&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Retry — &lt;a href=&quot;https://github.com/spring-projects/spring-retry&quot;&gt;repositório (arquivado em julho de 2026, substituído pelo Spring Framework 7)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IETF — &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9110.html#section-13.1.1&quot;&gt;RFC 9110, HTTP Semantics (requisições condicionais e o “lost update”)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Apache CouchDB — &lt;a href=&quot;https://docs.couchdb.org/en/stable/api/document/common.html&quot;&gt;API de documentos (&lt;code&gt;_rev&lt;/code&gt; e 409 Conflict)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Vlad Mihalcea — &lt;a href=&quot;https://vladmihalcea.com/tag/explicit-locking/&quot;&gt;artigos sobre explicit locking em JPA e Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stormatics — &lt;a href=&quot;https://stormatics.tech/blogs/ensuring-safe-data-modifications-in-postgresql-part-2&quot;&gt;Ensuring Safe Data Modifications in PostgreSQL, parte 2 (bloqueio otimista)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Dados</category><category>Banco de Dados</category><category>Concorrência</category><category>Spring</category><category>Trade-offs</category></item><item><title>Virtual threads no Java 21 — pinning e CLOSE_WAIT</title><link>https://blog.cesarschutz.com.br/posts/virtual-threads-pinning-close-wait/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/virtual-threads-pinning-close-wait/</guid><description>Por que um serviço Java 21 com virtual threads congela sem erro no log: pinning por synchronized (resolvido no Java 24, JEP 491) e CLOSE_WAIT como rastro. Thread dump, JFR, bulkhead e circuit breaker.</description><pubDate>Sat, 12 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Um serviço Java 21 com virtual threads para de responder no pico, sem nenhum erro no log, e o host acumula milhares de sockets em CLOSE_WAIT. Este post percorre a cadeia inteira desse incidente: por que o processo congela (o &lt;strong&gt;pinning&lt;/strong&gt; de virtual threads dentro de blocos &lt;code&gt;synchronized&lt;/code&gt;), por que o CLOSE_WAIT é o rastro e não a causa, como diagnosticar com thread dump e JFR, e o que continua valendo depois da correção: limites explícitos com bulkhead e circuit breaker, com código Java que você pode rodar.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Em quais versões isso acontece.&lt;/strong&gt; O pinning por &lt;code&gt;synchronized&lt;/code&gt; existe do &lt;strong&gt;Java 21 ao 23&lt;/strong&gt;. O Java 24 corrigiu o problema com a &lt;a href=&quot;https://openjdk.org/jeps/491&quot;&gt;JEP 491&lt;/a&gt;, e o &lt;strong&gt;Java 25 é a primeira LTS com a correção&lt;/strong&gt;. As seções 5 e 6 (gargalo, bulkhead e circuit breaker) valem para qualquer versão. O modelo de virtual threads está no &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-21/#virtual-threads&quot;&gt;post do Java 21&lt;/a&gt; e a correção, no &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#synchronized-n%C3%A3o-prende-mais-virtual-threads&quot;&gt;post do Java 25&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;1-o-sintoma-vivo-mudo-e-cheio-de-close_wait&quot;&gt;1. O sintoma: vivo, mudo e cheio de CLOSE_WAIT&lt;/h2&gt;
&lt;p&gt;Serviço de autorização de cartões, Spring Boot 3 com Tomcat embarcado, Java 21. O time ligou virtual threads para processar as requisições (&lt;code&gt;spring.&lt;wbr&gt;threads.&lt;wbr&gt;virtual.&lt;wbr&gt;enabled=true&lt;/code&gt;, disponível a partir do Spring Boot 3.2). Cada autorização chama o &lt;strong&gt;adquirente&lt;/strong&gt;, a empresa que processa a transação de cartão para o lojista.&lt;/p&gt;
&lt;p&gt;Dois dias depois, no pico da tarde, uma instância para de responder. Não devolve erro: simplesmente não responde. O health check estoura o tempo, o Kubernetes reinicia o pod, e tudo volta ao normal por algumas horas.&lt;/p&gt;
&lt;p&gt;Os sinais:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A JVM está viva. Sem OutOfMemoryError, sem exceção, sem stack trace no log.&lt;/li&gt;
&lt;li&gt;CPU baixa, memória estável, GC comportado.&lt;/li&gt;
&lt;li&gt;No host, milhares de sockets em CLOSE_WAIT.&lt;/li&gt;
&lt;li&gt;Não reproduz em homologação. O teste de carga sintético passa limpo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A leitura imediata costuma ser uma destas duas: “acabaram as threads” ou “tem um vazamento de conexão, alguém não está fechando socket”. As duas apontam para o lugar errado, e para ver por que é preciso ter quatro conceitos no lugar.&lt;/p&gt;
&lt;h2 id=&quot;2-quatro-conceitos-antes-do-diagnóstico&quot;&gt;2. Quatro conceitos antes do diagnóstico&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Socket&lt;/strong&gt; — a ponta que cada lado segura numa conexão de rede. Funciona como o telefone numa ligação: enquanto a ligação existe, ele está ocupado. Cada requisição HTTP em curso usa um, e socket é recurso finito: cada um conta no limite de arquivos abertos do processo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CLOSE_WAIT&lt;/strong&gt; — estado TCP que significa “o outro lado desligou, o seu ainda não”. Encerrar uma conexão exige que os dois lados desliguem, e quem desliga do seu lado é a aplicação, chamando &lt;code&gt;close()&lt;/code&gt;, não o sistema operacional (&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9293&quot;&gt;RFC 9293&lt;/a&gt;). Milhares de sockets nesse estado significam que o código parou de chegar à linha que fecha a conexão.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Platform thread&lt;/strong&gt; — a thread tradicional do Java, que corresponde a uma thread do sistema operacional (SO). É cara: só a pilha reserva 1 MB por padrão no Linux x64 (&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html&quot;&gt;documentação do &lt;code&gt;java&lt;/code&gt;&lt;/a&gt;). Por isso ninguém cria uma por requisição: cria-se um pool, e as requisições se revezam. O Tomcat do Spring Boot usa, por padrão, até 200 (&lt;a href=&quot;https://docs.spring.io/spring-boot/appendix/application-properties/index.html#application-properties.server.server.tomcat.threads.max&quot;&gt;&lt;code&gt;server.&lt;wbr&gt;tomcat.&lt;wbr&gt;threads.&lt;wbr&gt;max&lt;/code&gt;&lt;/a&gt;). O desperdício aparece quando o trabalho é esperar: 300 ms esperando o adquirente são 300 ms de uma thread ocupada sem fazer nada.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Virtual thread&lt;/strong&gt; — thread gerenciada pela JVM, não pelo SO. É barata a ponto de uma JVM poder ter milhões (&lt;a href=&quot;https://openjdk.org/jeps/444&quot;&gt;JEP 444&lt;/a&gt;). Ela não substitui as threads reais: para executar, é &lt;strong&gt;montada&lt;/strong&gt; sobre uma das poucas &lt;strong&gt;carrier threads&lt;/strong&gt;, que são platform threads de um pool da JVM (por padrão, uma por processador disponível). Quando a virtual thread bloqueia em I/O, a JVM normalmente a &lt;strong&gt;desmonta&lt;/strong&gt; da carrier e coloca outra no lugar. É esse revezamento que faz o modelo funcionar.&lt;/p&gt;
&lt;h2 id=&quot;3-o-diagnóstico-faltou-carrier-não-faltou-thread&quot;&gt;3. O diagnóstico: faltou carrier, não faltou thread&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Não faltou virtual thread, faltou carrier.&lt;/strong&gt; Virtual thread é barata, e a JVM cria quantas forem precisas. O gargalo é o punhado de threads reais embaixo delas. Se cada carrier fica presa a uma virtual thread que bloqueou e não desmontou, pode haver dezenas de milhares de virtual threads prontas, e nenhuma consegue executar. Esse estado tem nome: &lt;strong&gt;pinning&lt;/strong&gt; (a virtual thread fica “pregada” à carrier).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A causalidade é a inversa.&lt;/strong&gt; O CLOSE_WAIT não é a causa, é a impressão digital. As carriers travaram, então o código parou de rodar, então ninguém chegou à linha que fecha o socket. Os clientes estouraram o timeout e desligaram do lado deles. Milhares de CLOSE_WAIT são o retrato de uma aplicação congelada, não de um bug no fechamento de conexões.&lt;/p&gt;
&lt;p&gt;CLOSE_WAIT em massa tem outras causas conhecidas, e vale ter a lista na cabeça: &lt;code&gt;close()&lt;/code&gt; que não roda por causa de uma exceção, cliente HTTP sem try-with-resources, pool que nunca devolve a conexão. Todas têm algo em comum com esta: o código parou de chegar à linha que fecha. A diferença é que aqui ele parou de chegar a qualquer linha. É um dos primeiros lugares a olhar quando o processo está vivo, mas mudo.&lt;/p&gt;
&lt;p&gt;O diagrama mostra a cadeia completa, do pico de requisições até os sockets em CLOSE_WAIT:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/virtual-threads-pinning-close-wait/pinning-virtual-threads.svg&quot; alt=&quot;Diagrama: no Java 21 a 23, as virtual threads montadas nas 4 carriers bloqueiam dentro de synchronized e prendem as carriers; as demais esperam, ninguém fecha os sockets e eles se acumulam em CLOSE_WAIT; no Java 24 em diante, a JEP 491 corrige o synchronized&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;4-pinning-java-21-a-23&quot;&gt;4. Pinning (Java 21 a 23)&lt;/h2&gt;
&lt;p&gt;No Java 21, a virtual thread fica presa à carrier em dois casos (&lt;a href=&quot;https://openjdk.org/jeps/444&quot;&gt;JEP 444&lt;/a&gt;): quando bloqueia &lt;strong&gt;dentro de um bloco ou método &lt;code&gt;synchronized&lt;/code&gt;&lt;/strong&gt;, e durante um método nativo ou função estrangeira. O primeiro é o que pesa: segundo a JEP 491, resolvê-lo elimina quase todos os casos de pinning.&lt;/p&gt;
&lt;p&gt;O motivo é interno da JVM. Até o Java 23, ela registra como dona do monitor de um objeto (o lock que o &lt;code&gt;synchronized&lt;/code&gt; adquire) a &lt;strong&gt;platform thread&lt;/strong&gt;, ou seja, a carrier, e não a virtual thread. Se a virtual thread desmontasse ali dentro, outra virtual thread montada na mesma carrier pareceria dona do monitor, e a exclusão mútua se perderia (&lt;a href=&quot;https://openjdk.org/jeps/491&quot;&gt;JEP 491&lt;/a&gt;). Então a JVM não desmonta: a carrier fica bloqueada junto. E a JEP 444 é explícita: o escalonador &lt;strong&gt;não compensa&lt;/strong&gt; o pinning criando carriers extras.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Veja acontecer.&lt;/strong&gt; O programa abaixo roda 100 tarefas que esperam 100 ms cada, uma vez segurando um &lt;code&gt;synchronized&lt;/code&gt; e outra segurando um &lt;code&gt;ReentrantLock&lt;/code&gt;. Cada tarefa tem o próprio lock, então ninguém disputa nada: a única diferença é o tipo de lock.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:48&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;CarrierPresa.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutorService&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;locks&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ReentrantLock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;stream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IntStream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;CarrierPresa&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; esperarAdquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// espera de I/O: aqui a virtual thread deveria desmontar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentThread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;interrupt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; comSynchronized&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; monitor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Object&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// um por tarefa: ninguém disputa o lock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;synchronized&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;monitor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;esperarAdquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; comReentrantLock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ReentrantLock&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; lock &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ReentrantLock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// um por tarefa, como acima&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;esperarAdquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;finally&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;lock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;unlock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; medir&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Runnable&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; tarefa&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; inicio &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutorService&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; executor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IntStream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; executor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;submit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;tarefa&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;between&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;inicio&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toMillis&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Java &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Runtime&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;feature&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;synchronized:  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; medir&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CarrierPresa&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;comSynchronized&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt; ms&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;ReentrantLock: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; medir&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CarrierPresa&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;comReentrantLock&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt; ms&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Rodando com 4 carriers, como numa máquina de 4 vCPUs, nas imagens &lt;code&gt;eclipse-temurin:21&lt;/code&gt; e &lt;code&gt;eclipse-temurin:25&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:9&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Saída&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;$ java -Djdk.virtualThreadScheduler.parallelism=4 CarrierPresa.java&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Java 21&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;synchronized:  2581 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;ReentrantLock: 106 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;$ java -Djdk.virtualThreadScheduler.parallelism=4 CarrierPresa.java&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;Java 25&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;synchronized:  149 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;ReentrantLock: 104 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;No Java 21, com &lt;code&gt;synchronized&lt;/code&gt;, só 4 tarefas avançam por vez: 100 tarefas ÷ 4 carriers × 100 ms ≈ 2,5 s. Com &lt;code&gt;ReentrantLock&lt;/code&gt;, as 100 esperam juntas. No Java 25, os dois casos se comportam igual. Os tempos exatos variam de máquina para máquina; a proporção é o que importa.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nem sempre o &lt;code&gt;synchronized&lt;/code&gt; está no seu código.&lt;/strong&gt; A Netflix documentou exatamente esse quadro em julho de 2024: Spring Boot 3, Tomcat embarcado, Java 21, instâncias que paravam de responder e sockets acumulados em CLOSE_WAIT. Ali, o &lt;code&gt;synchronized&lt;/code&gt; vinha da biblioteca de tracing Brave (em &lt;code&gt;RealSpan.&lt;wbr&gt;finish&lt;/code&gt;). Dentro dele, as virtual threads esperavam um &lt;code&gt;ReentrantLock&lt;/code&gt; do reporter do Zipkin. As instâncias tinham 4 vCPUs, portanto 4 carriers. Com as quatro presas, quando o lock era liberado, a virtual thread que deveria recebê-lo não tinha carrier para executar, e nada mais andava. Os sockets em CLOSE_WAIT batiam com milhares de virtual threads que o Tomcat tinha criado e que nunca chegaram a executar.&lt;/p&gt;
&lt;p&gt;É também por isso que homologação passa limpo: pinning só vira travamento quando há concorrência suficiente para prender todas as carriers ao mesmo tempo. Com carga baixa, uma carrier presa passa despercebida.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Como se descobre&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Thread dump no formato novo.&lt;/strong&gt; O dump tradicional (&lt;code&gt;jstack&lt;/code&gt; ou &lt;code&gt;jcmd &amp;#x3C;pid&gt; Thread.&lt;wbr&gt;print&lt;/code&gt;) &lt;strong&gt;não mostra virtual threads&lt;/strong&gt; (&lt;a href=&quot;https://openjdk.org/jeps/444&quot;&gt;JEP 444&lt;/a&gt;); foi o que confundiu a Netflix no começo, porque o dump parecia ocioso. Use &lt;code&gt;jcmd &amp;#x3C;pid&gt; Thread.&lt;wbr&gt;dump_to_file -format=text dump.&lt;wbr&gt;txt&lt;/code&gt; (ou &lt;code&gt;-format=json&lt;/code&gt;; o nome do arquivo é obrigatório). Nele, as carriers (&lt;code&gt;ForkJoinPool-1-worker-N&lt;/code&gt;) aparecem executando &lt;code&gt;Continuation.&lt;wbr&gt;run&lt;/code&gt;, e as virtual threads montadas nelas aparecem paradas no mesmo ponto, dentro do &lt;code&gt;synchronized&lt;/code&gt;. Esse ponto é a resposta. As demais virtual threads aparecem sem stack: foram criadas e esperam uma carrier.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JFR (JDK Flight Recorder)&lt;/strong&gt;, o gravador de eventos embutido na JVM. O evento &lt;code&gt;jdk.&lt;wbr&gt;VirtualThreadPinned&lt;/code&gt; registra, com stack trace, cada vez que uma virtual thread fica parada presa à carrier por mais de 20 ms, o limiar padrão. O evento vem habilitado, mas só é gravado se houver uma gravação ativa: &lt;code&gt;java -XX:StartFlightRecording=filename=rec.&lt;wbr&gt;jfr ...&lt;/code&gt; e depois &lt;code&gt;jfr print --events jdk.&lt;wbr&gt;VirtualThreadPinned rec.&lt;wbr&gt;jfr&lt;/code&gt;. No &lt;code&gt;CarrierPresa.&lt;wbr&gt;java&lt;/code&gt;, o Java 21 grava 100 eventos, um por tarefa com &lt;code&gt;synchronized&lt;/code&gt;; o Java 25 grava zero. Manter o evento ligado em produção, com alerta, é uma das recomendações do &lt;a href=&quot;https://www.infoq.com/articles/virtual-threads-after-jdk24/&quot;&gt;artigo da InfoQ&lt;/a&gt; citado nas fontes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;-Djdk.&lt;wbr&gt;tracePinnedThreads=short&lt;/code&gt;&lt;/strong&gt; (ou &lt;code&gt;full&lt;/code&gt;), &lt;strong&gt;só do Java 21 ao 23&lt;/strong&gt;. Imprime o stack sempre que uma virtual thread bloqueia presa, e o frame marcado aponta o &lt;code&gt;synchronized&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot; style=&quot;--linhas:2&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;VirtualThread[#25]/runnable@ForkJoinPool-1-worker-2 reason:MONITOR&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;CarrierPresa.comSynchronized(CarrierPresa.java:21) &amp;#x3C;== monitors:1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A JEP 491 removeu essa propriedade no Java 24.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Como se resolve&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Subir para o Java 24 ou mais novo&lt;/strong&gt;, na prática para o &lt;strong&gt;Java 25&lt;/strong&gt;, a primeira LTS com a JEP 491. A partir dela, a virtual thread desmonta ao bloquear dentro de &lt;code&gt;synchronized&lt;/code&gt; ou em &lt;code&gt;Object.&lt;wbr&gt;wait()&lt;/code&gt;. É o conserto definitivo e vale também para o &lt;code&gt;synchronized&lt;/code&gt; das dependências. Os detalhes estão no &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#synchronized-n%C3%A3o-prende-mais-virtual-threads&quot;&gt;post do Java 25&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trocar &lt;code&gt;synchronized&lt;/code&gt; por &lt;code&gt;ReentrantLock&lt;/code&gt;&lt;/strong&gt;, se o serviço fica no Java 21. É a mesma exclusão mútua, mas a espera não prende a carrier. A JEP 444 recomenda a troca só onde o bloco roda com frequência e protege I/O potencialmente longo; blocos raros ou que só protegem operações em memória podem ficar como estão. No Java 24 em diante, a JEP 491 volta a recomendar &lt;code&gt;synchronized&lt;/code&gt; onde for prático.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Atualizar a dependência&lt;/strong&gt;, se o &lt;code&gt;synchronized&lt;/code&gt; está numa biblioteca e uma versão nova já trocou o lock. Se não trocou, não há o que refatorar no seu código: resta subir o Java.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Um upgrade de Java leva semanas, e no plantão a mitigação imediata é outra: desligar as virtual threads por configuração (&lt;code&gt;spring.&lt;wbr&gt;threads.&lt;wbr&gt;virtual.&lt;wbr&gt;enabled=false&lt;/code&gt;) e voltar ao pool tradicional. Perde escalabilidade, mas para de cair. Curativo e conserto são coisas separadas.&lt;/p&gt;
&lt;h2 id=&quot;5-o-gargalo-mudou-de-lugar&quot;&gt;5. O gargalo mudou de lugar&lt;/h2&gt;
&lt;p&gt;O Java 25 resolve o pinning por &lt;code&gt;synchronized&lt;/code&gt;, mas não resolve o que vem junto com as virtual threads. Esta parte vale para qualquer versão.&lt;/p&gt;
&lt;p&gt;No modelo antigo, o pool de 200 threads do Tomcat fazia dois trabalhos sem ninguém perceber: separava o trabalho de cada requisição &lt;strong&gt;e&lt;/strong&gt; limitava quantas requisições estavam em andamento, portanto quantas chamadas saíam do serviço ao mesmo tempo. Com virtual threads, cada requisição ganha a sua thread, e o segundo trabalho desaparece. A propriedade &lt;code&gt;server.&lt;wbr&gt;tomcat.&lt;wbr&gt;threads.&lt;wbr&gt;max&lt;/code&gt; nem tem efeito quando as virtual threads estão ligadas.&lt;/p&gt;
&lt;p&gt;Chegam 10 mil requisições no pico:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No Postgres&lt;/strong&gt;, nada é derrubado de imediato: forma-se fila. O pool de conexões do HikariCP tem teto (o padrão é 10; digamos que o time configurou 20). Vinte requisições pegam conexão e o resto espera. Quem não consegue conexão em 30 segundos, o &lt;code&gt;connectionTimeout&lt;/code&gt; padrão, recebe erro, e isso acontece em massa (&lt;a href=&quot;https://github.com/brettwooldridge/HikariCP&quot;&gt;HikariCP&lt;/a&gt;). Essa fila não existia antes: com 200 threads, no máximo 200 requisições pediam conexão, e as demais nem tinham começado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No adquirente&lt;/strong&gt;, é pior, porque o problema sai de casa. Milhares de chamadas simultâneas chegam a um terceiro com contrato para 500. Ele recusa ou fica lento, e aí você tem milhares de conexões abertas esperando.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Virtual threads não eliminam gargalo, mudam o gargalo de lugar.&lt;/strong&gt; É o mesmo deslocamento de sempre, em outra roupa: aumentar o pool de threads e derrubar o banco, subir réplicas e saturar a rede, paralelizar um job e estourar a cota de uma API de terceiro. Remover um limite não aumenta a capacidade, só empurra a fila para o próximo recurso escasso. O conserto é tornar explícito o que era implícito: um limite declarado em cada recurso compartilhado, com o número decidido por você em vez de herdado do tamanho do pool.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/virtual-threads-pinning-close-wait/gargalo-mudou-de-lugar.svg&quot; alt=&quot;Diagrama: antes, o pool de 200 threads separava o trabalho e limitava a saída; depois, 10.000 virtual threads sem limite formam fila no Postgres e sobrecarregam o adquirente; o conserto é bulkhead, circuit breaker e limite também antes do banco&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;6-as-três-peças-juntas&quot;&gt;6. As três peças juntas&lt;/h2&gt;
&lt;p&gt;São três trabalhos diferentes, e nenhum substitui o outro:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Virtual threads dão vazão&lt;/strong&gt;, isto é, mais trabalho em andamento ao mesmo tempo. Não deixam nada mais rápido: se o adquirente leva 300 ms, continua levando 300 ms. O que muda é quantas requisições cabem simultaneamente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bulkhead limita a saída.&lt;/strong&gt; É preventivo e funciona o tempo todo: declara quantas chamadas simultâneas podem sair do serviço para um destino. Devolve o limite que o pool de threads dava de graça.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Circuit breaker interrompe.&lt;/strong&gt; É reativo e só age quando o destino está mal: percebe a sequência de falhas e para de insistir por um tempo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Um sem o outro deixa buraco. Se o adquirente está lento, só com o bulkhead cada requisição ainda espera até 200 ms por uma vaga (o &lt;code&gt;maxWaitDuration&lt;/code&gt; dos exemplos abaixo), mais o tempo da própria chamada, para descobrir o que as últimas dezenas de falhas já tinham mostrado.&lt;/p&gt;
&lt;h3 id=&quot;vazão--o-efeito-das-virtual-threads&quot;&gt;Vazão — o efeito das virtual threads&lt;/h3&gt;
&lt;p&gt;Roda direto com &lt;code&gt;java Vazao.&lt;wbr&gt;java&lt;/code&gt; no Java 21 ou mais novo, sem dependência nenhuma. O &lt;code&gt;Thread.&lt;wbr&gt;sleep&lt;/code&gt; faz o papel da chamada ao adquirente.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:30&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Vazao.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutorService&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;stream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IntStream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Vazao&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; chamadaAoAdquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// espera de I/O: a thread não faz nada aqui&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentThread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;interrupt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; medir&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutorService&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; executor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; inicio &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;executor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// close() espera todas terminarem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IntStream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                     &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; executor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;submit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Vazao&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;chamadaAoAdquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;between&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;inicio&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toMillis&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pool de 200 threads: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; medir&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;newFixedThreadPool&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt; ms&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;virtual threads:     &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; medir&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt; ms&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:2&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Saída (eclipse-temurin:21)&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;pool de 200 threads: 1623 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;virtual threads:     324 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;São mil chamadas de 300 ms. Com 200 threads, elas saem em cinco levas: no mínimo 1500 ms, um pouco mais na prática, porque criar as threads também custa. Com virtual threads, todas ficam em andamento juntas, perto de 300 ms. É esse número que deveria acender a luz amarela: mil chamadas simultâneas saindo para um terceiro.&lt;/p&gt;
&lt;h3 id=&quot;bulkhead--o-limite-sem-dependência&quot;&gt;Bulkhead — o limite, sem dependência&lt;/h3&gt;
&lt;p&gt;Também roda sozinho. O &lt;code&gt;Semaphore&lt;/code&gt; limita a 100 as chamadas simultâneas, e o programa mostra o pico real de chamadas em andamento e quantas foram recusadas pelo próprio serviço.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:48&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;BulkheadSimples.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutorService&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Semaphore&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TimeUnit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;concurrent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;atomic&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;util&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;stream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IntStream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;BulkheadSimples&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Semaphore&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; limite &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Semaphore&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; emVoo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pico &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; recusadas &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; AtomicInteger&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; capturar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;entrar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// não conseguiu vaga a tempo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;recusadas&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;incrementAndGet&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// recusa rápida, decidida por você&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; agora &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; emVoo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;incrementAndGet&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pico&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;updateAndGet&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Math&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;max&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; agora&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentThread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;interrupt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;finally&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;emVoo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;decrementAndGet&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;limite&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;release&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// sem isto, o limite vaza até zerar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;boolean&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entrar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; limite&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;tryAcquire&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; TimeUnit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;MILLISECONDS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;InterruptedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentThread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;interrupt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ExecutorService&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; executor &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Executors&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;IntStream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; executor&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;submit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;BulkheadSimples&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;capturar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;pico de chamadas simultâneas: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pico&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;recusadas por você:           &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; recusadas&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:2&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Saída&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;pico de chamadas simultâneas: 100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;recusadas por você:           900&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O pico nunca passa de 100, por mais requisições que cheguem. As 100 primeiras entram; as outras 900 esperam 200 ms por uma vaga, e nenhuma vaga abre antes dos 300 ms da chamada, então são recusadas. O &lt;code&gt;finally&lt;/code&gt; é o ponto crítico do código: se a permissão não for devolvida em todo caminho de saída, inclusive em exceção, o limite encolhe sozinho até travar tudo.&lt;/p&gt;
&lt;p&gt;O nome geral desse freio é &lt;strong&gt;backpressure&lt;/strong&gt;: quem está sobrecarregado sinaliza a quem produz que desacelere, em vez de aceitar tudo e desmoronar. Semáforo, fila limitada e rate limit são formas de aplicar. Virtual threads não aplicam backpressure sozinhas, elas aceitam tudo o que chega; o semáforo é você declarando o freio.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;De onde vem o número.&lt;/strong&gt; Não é chute nem é o contrato do parceiro (o contrato é o teto, não a meta). Vem da &lt;a href=&quot;https://en.wikipedia.org/wiki/Little%27s_law&quot;&gt;lei de Little&lt;/a&gt;: chamadas em andamento = vazão × tempo médio de resposta. Cem chamadas por segundo com resposta em 300 ms dão 30 chamadas em andamento, em média. Some uma folga para picos e meça. O 100 dos exemplos é só ilustrativo.&lt;/p&gt;
&lt;h3 id=&quot;circuit-breaker--com-resilience4j&quot;&gt;Circuit breaker — com Resilience4j&lt;/h3&gt;
&lt;p&gt;Aqui entra dependência. No Maven:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;pom.xml&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;XML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;xml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;io.github.resilience4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;resilience4j-circuitbreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;2.4.0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O exemplo abaixo simula um parceiro que falha por um tempo e depois volta, e imprime cada mudança de estado:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:43&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Breaker.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;github&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;resilience4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;circuitbreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CallNotPermittedException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;github&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;resilience4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;circuitbreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CircuitBreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;github&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;resilience4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;circuitbreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Breaker&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;volatile&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;boolean&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; parceiroFora &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; capturar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;parceiroFora&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; RuntimeException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;adquirente indisponível&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;CAPTURADO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; args&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; config &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CircuitBreakerConfig&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;custom&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;slidingWindowType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;SlidingWindowType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;COUNT_BASED&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;slidingWindowSize&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// olha as últimas 20 chamadas&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;minimumNumberOfCalls&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                     &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// só decide depois de 10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;failureRateThreshold&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                     &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// abre com 50% de falha&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;waitDurationInOpenState&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ofSeconds&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;permittedNumberOfCallsInHalfOpenState&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// sondagem ao voltar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CircuitBreaker&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; breaker &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CircuitBreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;adquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; config&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;breaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getEventPublisher&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;               &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;onStateTransition&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;e &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getStateTransition&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;60&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;40&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; parceiroFora &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// parceiro se recupera&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; resposta &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; breaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;executeSupplier&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Breaker&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;capturar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; resposta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CallNotPermittedException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;: barrado pelo breaker, sem sair da aplicação&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;RuntimeException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;: falhou no parceiro&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sleep&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;150&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para rodar sem Maven, basta pôr no classpath os JARs &lt;code&gt;resilience4j-circuitbreaker&lt;/code&gt;, &lt;code&gt;resilience4j-core&lt;/code&gt; e &lt;code&gt;slf4j-api&lt;/code&gt; (&lt;code&gt;java -cp &quot;lib/*&quot; Breaker.&lt;wbr&gt;java&lt;/code&gt;). A saída, resumida (o SLF4J imprime antes um aviso de que não há logger configurado, que pode ser ignorado):&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:23&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Saída (resumida)&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;1: falhou no parceiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;9: falhou no parceiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;&gt;&gt; State transition from CLOSED to OPEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;10: falhou no parceiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;11: barrado pelo breaker, sem sair da aplicação&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;29: barrado pelo breaker, sem sair da aplicação&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;&gt;&gt; State transition from OPEN to HALF_OPEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;30: falhou no parceiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;31: falhou no parceiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;&gt;&gt; State transition from HALF_OPEN to OPEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;32: falhou no parceiro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;33: barrado pelo breaker, sem sair da aplicação&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;51: barrado pelo breaker, sem sair da aplicação&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;&gt;&gt; State transition from OPEN to HALF_OPEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;52: CAPTURADO&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;53: CAPTURADO&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;&gt;&gt; State transition from HALF_OPEN to CLOSED&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;54: CAPTURADO&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1a2124;--1:#e7e9e4&quot;&gt;60: CAPTURADO&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A sequência inteira aparece:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;As 10 primeiras chamadas falham de verdade. Na décima, a taxa de falha chega a 100% e o breaker abre. A linha &lt;code&gt;&gt;&gt;&lt;/code&gt; sai antes de &lt;code&gt;10: falhou&lt;/code&gt; porque o evento dispara quando o breaker registra a falha, antes de a exceção chegar ao &lt;code&gt;catch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Durante 3 segundos (cerca de 20 voltas de 150 ms), as chamadas são barradas sem sair da aplicação.&lt;/li&gt;
&lt;li&gt;Na primeira chamada depois desse tempo, o breaker passa a meio-aberto e deixa 3 chamadas passarem para sondar. O parceiro ainda está fora, então ele abre de novo.&lt;/li&gt;
&lt;li&gt;O parceiro volta na chamada 40, mas o breaker só descobre na sondagem seguinte, na 52. As 3 chamadas de sondagem dão certo e o breaker fecha.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Os três estados: &lt;strong&gt;fechado&lt;/strong&gt; é o saudável, com a corrente passando (o nome confunde no começo); &lt;strong&gt;aberto&lt;/strong&gt; é o disjuntor desarmado, com falha imediata e sem tráfego; &lt;strong&gt;meio-aberto&lt;/strong&gt; deixa poucas chamadas passarem para sondar e decide se fecha ou abre de novo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;De onde vem, e o que ele não é.&lt;/strong&gt; O circuit breaker não tem relação com virtual threads. Ele é bem mais antigo: aparece no livro &lt;em&gt;Release It!&lt;/em&gt;, de Michael Nygard, de 2007, e ficou conhecido com o Hystrix, que a Netflix abriu em 2012, mais de dez anos antes das virtual threads. O problema que ele resolve é de sistema distribuído: parar de insistir com um serviço que está mal. Vale em qualquer linguagem, com ou sem threads, síncrono ou assíncrono. O mesmo vale para o bulkhead, que vem do mesmo livro; o nome vem das anteparas que dividem o casco de um navio em compartimentos estanques.&lt;/p&gt;
&lt;p&gt;A relação com este caso é outra, e vale guardar assim: &lt;strong&gt;virtual threads não criaram a necessidade, tiraram o disfarce.&lt;/strong&gt; O pool de 200 threads dava um limite acidental de graça, e esse limite mascarava a ausência das duas proteções. Ao remover o pool, o que estava escondido apareceu.&lt;/p&gt;
&lt;p&gt;Isso importa na hora de aplicar. Quem conclui que “circuit breaker é coisa de virtual thread” deixa de usá-lo nos serviços que continuam com pool, e lá ele é igualmente necessário; só que a falha demora mais a aparecer.&lt;/p&gt;
&lt;h3 id=&quot;em-produção-com-spring-boot&quot;&gt;Em produção, com Spring Boot&lt;/h3&gt;
&lt;p&gt;No Spring Boot, o mesmo vira configuração. O starter do Resilience4j exige o AOP e o Actuator do Spring Boot:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:13&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;pom.xml&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;XML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;xml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;io.github.resilience4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;resilience4j-spring-boot3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;2.4.0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;org.springframework.boot&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;spring-boot-starter-aop&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;org.springframework.boot&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;spring-boot-starter-actuator&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;artifactId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;dependency&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:15&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;application.yml&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;YAML&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;resilience4j&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bulkhead&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instances&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;adquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;maxConcurrentCalls&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;maxWaitDuration&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;200ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;circuitbreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instances&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;adquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;slidingWindowType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;COUNT_BASED&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;slidingWindowSize&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;20&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;minimumNumberOfCalls&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;failureRateThreshold&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;waitDurationInOpenState&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;3s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;permittedNumberOfCallsInHalfOpenState&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:10&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@Bulkhead&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;adquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt;@CircuitBreaker&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;adquirente&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;fallbackMethod&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#835B0F;--1:#E0B560&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;indisponivel&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Resposta&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; capturar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Cobranca&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; adquirenteClient&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;capturar&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;cobranca&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// mesma assinatura do método protegido, mais a exceção no final&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Resposta&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; indisponivel&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Cobranca&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Throwable&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; causa&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Resposta&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;negada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;INDISPONIVEL_TEMPORARIAMENTE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Com o Actuator, as métricas do bulkhead e do breaker saem pelo Micrometer, e dali para o Prometheus, o Dynatrace ou a ferramenta de observabilidade do time.&lt;/p&gt;
&lt;p&gt;Cinco detalhes que costumam morder:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use o bulkhead de semáforo, não o de thread pool.&lt;/strong&gt; O Resilience4j tem as duas variantes, e a de thread pool reintroduz exatamente o pool que você acabou de tirar. &lt;code&gt;@Bulkhead&lt;/code&gt; sem &lt;code&gt;type&lt;/code&gt; já usa o de semáforo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;As anotações só funcionam através do proxy do Spring.&lt;/strong&gt; Se outro método da mesma classe chama &lt;code&gt;capturar()&lt;/code&gt; direto, o bulkhead e o breaker não rodam. O motivo está em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/aop-jdk-proxy-cglib/#a-pegadinha-da-self-invocation&quot;&gt;A pegadinha da self-invocation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timeout é pré-requisito.&lt;/strong&gt; Sem tempo limite na chamada HTTP, ela não falha: fica pendurada. Uma chamada que nunca termina nunca entra na conta do breaker, que então não abre, e as conexões esperando se acumulam.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O limiar é proporção, não contagem.&lt;/strong&gt; Baixo demais, o breaker abre por qualquer soluço; alto demais, nunca abre. E o &lt;code&gt;minimumNumberOfCalls&lt;/code&gt; evita que três falhas às três da manhã, com tráfego baixo, abram o disjuntor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cuidado com a ordem dos aspectos.&lt;/strong&gt; Por padrão, o Resilience4j aplica, de fora para dentro: Retry, CircuitBreaker, RateLimiter, TimeLimiter, Bulkhead (a ordem pode ser mudada por propriedades como &lt;code&gt;resilience4j.&lt;wbr&gt;retry.&lt;wbr&gt;retryAspectOrder&lt;/code&gt;). Sendo o mais externo, o retry repete o conjunto inteiro. Por isso ele precisa de espera crescente com um pouco de aleatoriedade (&lt;a href=&quot;https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/&quot;&gt;backoff exponencial com jitter&lt;/a&gt;), ou você cria uma tempestade de retries que derruba de vez quem já estava mal. Em cobrança, retry também exige idempotência: veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;Chave de idempotência&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;o-que-devolver-para-quem-foi-recusado&quot;&gt;O que devolver para quem foi recusado&lt;/h3&gt;
&lt;p&gt;Em cartão, &lt;strong&gt;negar não é falhar&lt;/strong&gt;. Um erro genérico obriga a maquininha a decidir sem informação. Uma negativa com um código de indisponibilidade temporária diz que o problema é passageiro, e não uma recusa por saldo ou por suspeita de fraude. Quem recebe pode tentar de novo depois, e quem atende o portador (o titular do cartão) sabe o que aconteceu.&lt;/p&gt;
&lt;p&gt;O critério para escolher entre recusa imediata e nova tentativa é o orçamento de tempo. Uma autorização síncrona tem poucos segundos, então recusar rápido é o caminho principal. Retentar fica para os fluxos assíncronos, como ajuste financeiro, estorno e processamento em lote, onde a espera cabe.&lt;/p&gt;
&lt;h2 id=&quot;7-o-que-fica-depois-do-conserto&quot;&gt;7. O que fica depois do conserto&lt;/h2&gt;
&lt;p&gt;Corrigido o pinning e declarados os limites, sobram decisões que o incidente deixa para o time. São as que eu levaria para a retrospectiva.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Um upgrade por vez.&lt;/strong&gt; Java 25 e Spring Boot 4 no mesmo deploy apagam a pista: se algo quebrar, não dá para saber qual dos dois foi. Suba o Java primeiro, que é o que conserta o pinning, estabilize, e só então o framework. O &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/guia-atualizacoes-java/&quot;&gt;guia de atualizações do Java&lt;/a&gt; detalha o processo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O que faltava no teste de carga.&lt;/strong&gt; Ele passou limpo porque não reproduzia o que derruba: concorrência suficiente para prender todas as carriers ao mesmo tempo, o mesmo número de vCPUs da produção (carriers = processadores), as mesmas bibliotecas e agentes (no caso da Netflix, o &lt;code&gt;synchronized&lt;/code&gt; estava no tracing) e duração para acumular. Teste sem o gargalo da produção só mede o que não importa.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A métrica que avisa que o pinning voltou.&lt;/strong&gt; O evento &lt;code&gt;jdk.&lt;wbr&gt;VirtualThreadPinned&lt;/code&gt; do JFR é a fonte direta: com uma gravação contínua ou com &lt;em&gt;JFR event streaming&lt;/em&gt; (&lt;code&gt;jdk.&lt;wbr&gt;jfr.&lt;wbr&gt;consumer.&lt;wbr&gt;RecordingStream&lt;/code&gt;, &lt;a href=&quot;https://openjdk.org/jeps/349&quot;&gt;JEP 349&lt;/a&gt;) exportando a contagem para o Micrometer, qualquer ocorrência acima do limiar vira alerta. Os sinais indiretos já estavam no incidente: latência subindo com CPU baixa e a contagem de sockets em CLOSE_WAIT no host. Vale manter mesmo no Java 25: ainda há pinning quando código nativo chama de volta código Java que bloqueia (&lt;a href=&quot;https://openjdk.org/jeps/491&quot;&gt;JEP 491&lt;/a&gt;), e o Java 26 tirou um dos casos restantes, a espera pela inicialização de uma classe (&lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-29/#virtual-threads-liberam-a-carrier-enquanto-esperam-a-inicializa%C3%A7%C3%A3o-de-uma-classe&quot;&gt;post do Java 29&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ThreadLocal&lt;/code&gt; deixa de ser cache.&lt;/strong&gt; Virtual threads não devem ser reaproveitadas em pool, então o velho hábito de guardar um objeto caro por thread vira um objeto por requisição, e, como elas podem ser muitas, o consumo de memória só aparece sob carga alta (&lt;a href=&quot;https://openjdk.org/jeps/444&quot;&gt;JEP 444&lt;/a&gt;). Para propagar contexto (usuário autenticado, trace id, tenant), o substituto é &lt;strong&gt;Scoped Values&lt;/strong&gt;, finalizado no Java 25 (&lt;a href=&quot;https://openjdk.org/jeps/506&quot;&gt;JEP 506&lt;/a&gt;; detalhes no &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/java-25/#scoped-values&quot;&gt;post do Java 25&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O disfarce caiu, o problema era antigo.&lt;/strong&gt; Bulkhead e circuit breaker existem desde 2007 e servem igual aos serviços que continuam com pool de threads; ali a falha só demora mais para aparecer. Se a conclusão da retrospectiva for “circuit breaker é coisa de virtual thread”, ela saiu errada.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OpenJDK — &lt;a href=&quot;https://openjdk.org/jeps/444&quot;&gt;JEP 444: Virtual Threads&lt;/a&gt; (casos de pinning, carriers, thread dump, JFR, &lt;code&gt;ThreadLocal&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;OpenJDK — &lt;a href=&quot;https://openjdk.org/jeps/491&quot;&gt;JEP 491: Synchronize Virtual Threads without Pinning&lt;/a&gt; (Java 24)&lt;/li&gt;
&lt;li&gt;OpenJDK — &lt;a href=&quot;https://openjdk.org/jeps/506&quot;&gt;JEP 506: Scoped Values&lt;/a&gt; (Java 25)&lt;/li&gt;
&lt;li&gt;OpenJDK — &lt;a href=&quot;https://openjdk.org/jeps/349&quot;&gt;JEP 349: JFR Event Streaming&lt;/a&gt; (Java 14)&lt;/li&gt;
&lt;li&gt;Oracle — &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html&quot;&gt;Virtual Threads&lt;/a&gt; (guia do Java 21)&lt;/li&gt;
&lt;li&gt;Oracle — &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html&quot;&gt;The java Command&lt;/a&gt; (tamanho padrão da pilha, &lt;code&gt;-Xss&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Netflix Technology Blog — &lt;a href=&quot;https://netflixtechblog.com/java-21-virtual-threads-dude-wheres-my-lock-3052540e231d&quot;&gt;Java 21 Virtual Threads: Dude, Where’s My Lock?&lt;/a&gt; (julho de 2024)&lt;/li&gt;
&lt;li&gt;InfoQ — &lt;a href=&quot;https://www.infoq.com/articles/virtual-threads-after-jdk24/&quot;&gt;Virtual Threads after JDK 24: What Changed for Production Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IETF — &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9293&quot;&gt;RFC 9293: Transmission Control Protocol&lt;/a&gt; (estados TCP, CLOSE-WAIT)&lt;/li&gt;
&lt;li&gt;Spring Boot — &lt;a href=&quot;https://docs.spring.io/spring-boot/appendix/application-properties/index.html&quot;&gt;Common Application Properties&lt;/a&gt; (&lt;code&gt;spring.&lt;wbr&gt;threads.&lt;wbr&gt;virtual.&lt;wbr&gt;enabled&lt;/code&gt;, &lt;code&gt;server.&lt;wbr&gt;tomcat.&lt;wbr&gt;threads.&lt;wbr&gt;max&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Spring Boot — &lt;a href=&quot;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.2-Release-Notes&quot;&gt;Spring Boot 3.2 Release Notes&lt;/a&gt; (suporte a virtual threads)&lt;/li&gt;
&lt;li&gt;HikariCP — &lt;a href=&quot;https://github.com/brettwooldridge/HikariCP&quot;&gt;README&lt;/a&gt; (&lt;code&gt;maximumPoolSize&lt;/code&gt; e &lt;code&gt;connectionTimeout&lt;/code&gt; padrão)&lt;/li&gt;
&lt;li&gt;Resilience4j — &lt;a href=&quot;https://resilience4j.readme.io/docs/circuitbreaker&quot;&gt;CircuitBreaker&lt;/a&gt;, &lt;a href=&quot;https://resilience4j.readme.io/docs/bulkhead&quot;&gt;Bulkhead&lt;/a&gt; e &lt;a href=&quot;https://resilience4j.readme.io/docs/getting-started-3&quot;&gt;Getting Started com Spring Boot 3&lt;/a&gt; (dependências, ordem dos aspectos, fallback)&lt;/li&gt;
&lt;li&gt;Martin Fowler — &lt;a href=&quot;https://martinfowler.com/bliki/CircuitBreaker.html&quot;&gt;CircuitBreaker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ACM Digital Library — &lt;a href=&quot;https://dl.acm.org/doi/10.5555/1200767&quot;&gt;Release It!: Design and Deploy Production-Ready Software&lt;/a&gt; (Michael T. Nygard, 2007)&lt;/li&gt;
&lt;li&gt;Netflix Technology Blog — &lt;a href=&quot;https://netflixtechblog.com/introducing-hystrix-for-resilience-engineering-13531c1ab362&quot;&gt;Introducing Hystrix for Resilience Engineering&lt;/a&gt; (novembro de 2012)&lt;/li&gt;
&lt;li&gt;Wikipedia — &lt;a href=&quot;https://en.wikipedia.org/wiki/Little%27s_law&quot;&gt;Little’s law&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS Architecture Blog — &lt;a href=&quot;https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/&quot;&gt;Exponential Backoff And Jitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Desenvolvimento de Software</category><category>Virtual Threads</category><category>Concorrência</category><category>JVM</category></item><item><title>Efeito externo sem registro local — a cobrança passou e o banco não gravou</title><link>https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/</guid><description>A captura no adquirente passa e a gravação no seu banco falha: grave a intenção antes de causar o efeito. Escrita dupla, outbox e relay com SQL testado, conciliação, CDC, event sourcing e 2PC.</description><pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Seu serviço cobrou o cliente no &lt;strong&gt;adquirente&lt;/strong&gt; (a empresa que processa a transação de cartão), mas o processo morreu antes de gravar a cobrança no banco. O dinheiro saiu e você não tem registro disso. Este post mostra por que retry e alerta não resolvem, dá nome ao problema (a &lt;strong&gt;escrita dupla&lt;/strong&gt;) e apresenta o desenho que garante que todo efeito externo deixa rastro local: gravar a intenção antes de agir, com tabela outbox, relay e conciliação, com o SQL testado no PostgreSQL. É a continuação de &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;Chave de idempotência&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;1-o-cenário-a-captura-passou-e-o-processo-morreu&quot;&gt;1. O cenário: a captura passou e o processo morreu&lt;/h2&gt;
&lt;p&gt;A chave de idempotência está implantada e funcionando. Um dia, o gráfico mostra cobranças que aparecem na fatura do cliente, mas não existem no seu banco.&lt;/p&gt;
&lt;p&gt;Investigando, o fluxo é este: o serviço chama o adquirente, a &lt;strong&gt;captura&lt;/strong&gt; (a efetivação da cobrança) passa, e só depois o serviço grava a cobrança no Postgres. Entre as duas coisas, o processo morreu.&lt;/p&gt;
&lt;p&gt;Antes de desenhar qualquer coisa, três perguntas mudam a solução: com que frequência isso acontece, se o adquirente permite consultar o status de uma cobrança depois, e quanto tempo o cliente aceita esperar pela resposta. As respostas definem o tamanho da conciliação, se ela é possível e se a captura pode sair do request.&lt;/p&gt;
&lt;h2 id=&quot;2-por-que-retry-e-alerta-não-resolvem&quot;&gt;2. Por que retry e alerta não resolvem&lt;/h2&gt;
&lt;p&gt;A primeira ideia costuma ser envolver a chamada em try/catch: se a gravação falhar, retry algumas vezes; se ainda assim falhar, log e alerta para o time olhar.&lt;/p&gt;
&lt;p&gt;Retry e alerta tratam o sintoma depois que o dano já existe. Nenhum dos dois muda o fato estrutural: o efeito externo aconteceu antes de existir qualquer registro local.&lt;/p&gt;
&lt;p&gt;E se o processo morre de verdade, não há try/catch que rode: o bloco de tratamento morre junto. Isso acontece quando o contêiner é encerrado à força (SIGKILL), seja por falta de memória (OOM), seja num deploy que estoura o prazo de desligamento. O post &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/sigterm-sigkill-kubernetes/&quot;&gt;SIGTERM e SIGKILL&lt;/a&gt; detalha esse ciclo no Kubernetes.&lt;/p&gt;
&lt;p&gt;O detalhe mais desconfortável: a chave de idempotência do post anterior não protege aqui. Ela só existiria dentro da linha que não chegou a ser gravada, então o retry seguinte chega sem nada para comparar e captura de novo.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/efeito-externo-sem-registro.svg&quot; alt=&quot;Diagrama: o serviço captura no adquirente, o processo morre antes do INSERT, não sobra registro local e o retry cobra de novo&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;3-o-problema-tem-nome-escrita-dupla&quot;&gt;3. O problema tem nome: escrita dupla&lt;/h2&gt;
&lt;p&gt;Escrever em dois sistemas que não compartilham transação é a &lt;strong&gt;escrita dupla&lt;/strong&gt; (&lt;em&gt;dual write&lt;/em&gt;). Seu banco não sabe nada sobre o adquirente, e não existe commit que cubra os dois. Uma falha entre as duas escritas deixa os dois lados discordando. A forma é sempre a mesma, mude o que mudar de nome: banco mais fila, banco mais cache, banco mais índice de busca, banco mais API de terceiro.&lt;/p&gt;
&lt;p&gt;O que não resolve, mesmo parecendo que resolve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inverter a ordem&lt;/strong&gt;: gravar a cobrança como concluída e só depois chamar o adquirente troca o problema de lado. Em vez de cobrança sem registro, você passa a ter registro sem cobrança.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retry no catch&lt;/strong&gt;: só roda se o processo continuar vivo. E, quando a falha é ambígua (um timeout, por exemplo), ela não diz se a operação aconteceu; repetir às cegas pode transformar perda em duplicidade.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transação distribuída com 2PC&lt;/strong&gt; (&lt;em&gt;two-phase commit&lt;/em&gt;): um coordenador pergunta a todos os participantes se podem confirmar e só então manda confirmar. Existe e funciona entre recursos que falam o protocolo (o PostgreSQL tem &lt;code&gt;PREPARE TRANSACTION&lt;/code&gt;), mas é bloqueante: os participantes seguram travas enquanto esperam a decisão e, se o coordenador falha, ficam presos. E uma API HTTP de terceiro, como a do adquirente, não é participante de 2PC. É a resposta que parece óbvia para quem acabou de conhecer o problema, e saber por que ela é rejeitada vale mais do que saber que ela existe.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;4-grave-a-intenção-antes-de-causar-o-efeito&quot;&gt;4. Grave a intenção antes de causar o efeito&lt;/h2&gt;
&lt;p&gt;O que resolve é mudar o que se escreve primeiro: &lt;strong&gt;grave a intenção antes de causar o efeito.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Numa única transação do Postgres, o serviço grava a cobrança com status PENDENTE e, na &lt;strong&gt;tabela outbox&lt;/strong&gt; (uma tabela de eventos a publicar), o evento &lt;code&gt;CobrancaIniciada&lt;/code&gt;. Ou as duas linhas existem, ou nenhuma.&lt;/li&gt;
&lt;li&gt;Só depois do commit ele chama o adquirente, enviando a mesma chave de idempotência, se o adquirente aceitar uma (a API da Stripe, por exemplo, aceita o cabeçalho &lt;code&gt;Idempotency-Key&lt;/code&gt;). Assim, repetir a captura é seguro.&lt;/li&gt;
&lt;li&gt;Com a resposta, atualiza a linha para CAPTURADO e grava o evento &lt;code&gt;CobrancaCapturada&lt;/code&gt; no outbox, também numa transação só.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Em SQL, com duas tabelas mínimas:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:16&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;esquema.sql&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TABLE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id              &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;GENERATED&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ALWAYS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IDENTITY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;idempotency_key &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UNIQUE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor_centavos  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- PENDENTE, CAPTURADO ou FALHOU&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;criada_em       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;timestamptz&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DEFAULT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;atualizada_em   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;timestamptz&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DEFAULT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TABLE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; outbox (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id           &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;GENERATED&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ALWAYS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IDENTITY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;tipo         &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;payload      jsonb &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;criado_em    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;timestamptz&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DEFAULT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;publicado_em &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;timestamptz&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;             &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- NULL = ainda não publicado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O passo 1 é uma transação com dois INSERTs:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:11&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;intencao.sql&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca (idempotency_key, valor_centavos, &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;7f3a9c1e-2b4d-4f60-9a71-0c5e8d2b3a44&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;25000&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;PENDENTE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; outbox (tipo, payload)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;CobrancaIniciada&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;{&quot;idempotency_key&quot;: &quot;7f3a9c1e-2b4d-4f60-9a71-0c5e8d2b3a44&quot;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&quot;valor_centavos&quot;: 25000}&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Se o processo cair entre um INSERT e o outro, ou antes do COMMIT, não fica nada: num teste forçando um erro no segundo INSERT, a cobrança do primeiro sumiu junto no rollback. E o passo 3 tem a mesma forma, um UPDATE na cobrança e um INSERT no outbox dentro de &lt;code&gt;BEGIN&lt;/code&gt; e &lt;code&gt;COMMIT&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Se o processo cair depois do commit, no meio do caminho, sobra um PENDENTE contando exatamente o que faltou terminar. E o retry do cliente agora esbarra numa linha que existe: em vez de capturar às cegas, o serviço sabe que precisa descobrir o que aconteceu com aquela chave.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/grave-intencao-antes-de-agir.svg&quot; alt=&quot;Diagrama: a cobrança PENDENTE e o evento do outbox são gravados na mesma transação antes da captura; relay e conciliação rodam fora do request&quot;&gt;&lt;/p&gt;
&lt;p&gt;Duas peças completam o desenho, as duas fora do request.&lt;/p&gt;
&lt;h3 id=&quot;relay-do-outbox&quot;&gt;Relay do outbox&lt;/h3&gt;
&lt;p&gt;Um processo separado lê a tabela outbox, publica os eventos no broker de mensagens e os marca como enviados:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:16&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;relay.sql&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BEGIN&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id, tipo, payload&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; outbox&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; publicado_em &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NULL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SKIP&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LOCKED;   &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- outro relay em paralelo pega outras linhas&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- publica cada evento no broker&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; outbox&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; publicado_em &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IN&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);       &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- os ids do lote publicado&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;COMMIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code&gt;SKIP LOCKED&lt;/code&gt; permite rodar mais de um relay sem que dois publiquem o mesmo lote: num teste com dois workers ao mesmo tempo, cada um levou três eventos diferentes. Se o relay cair depois de publicar e antes do COMMIT, o lote volta a ficar disponível e é publicado de novo, então a entrega é &lt;strong&gt;pelo menos uma vez&lt;/strong&gt; e quem consome precisa ser idempotente. É o mesmo princípio do post anterior, agora do lado de quem lê. No post sobre &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/w3c-trace-context/&quot;&gt;W3C Trace Context&lt;/a&gt;, o &lt;code&gt;traceparent&lt;/code&gt; viaja por esse mesmo outbox.&lt;/p&gt;
&lt;h3 id=&quot;conciliação&quot;&gt;Conciliação&lt;/h3&gt;
&lt;p&gt;Um job varre os PENDENTE antigos e pergunta o status ao adquirente:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:7&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;conciliacao.sql&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id, idempotency_key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;PENDENTE&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AND&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; criada_em &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; interval &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;2 minutes&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ORDER BY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; criada_em&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;LIMIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FOR&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SKIP&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LOCKED;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Para cada linha, o job consulta o adquirente pela chave. Se a captura passou, atualiza para CAPTURADO e grava o evento no outbox, na mesma transação; se não passou, marca como falha ou tenta de novo com a mesma chave. Os dois minutos são o prazo que uma cobrança pode ficar sem desfecho antes de alguém perguntar: vêm do tempo normal do request com folga, não de chute. É a rede que pega o que escapou.&lt;/p&gt;
&lt;p&gt;O princípio por trás das três peças é o do &lt;em&gt;write-ahead log&lt;/em&gt; do banco, em que a mudança é registrada no log antes de ser aplicada, levado para o nível da aplicação. O artigo de Brandur Leach sobre chaves de idempotência formaliza a mesma ideia como fases atômicas com pontos de recuperação. Aparece em upload em duas etapas, emissão de nota fiscal, provisionamento de recurso em nuvem: sempre que a falha precisa deixar rastro em vez de silêncio.&lt;/p&gt;
&lt;h2 id=&quot;5-variações-cdc-e-event-sourcing&quot;&gt;5. Variações: CDC e event sourcing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Change Data Capture (CDC)&lt;/strong&gt;: em vez de um processo consultar a tabela outbox de tempos em tempos (&lt;em&gt;polling&lt;/em&gt;), uma ferramenta lê o log de transações do próprio banco e publica cada mudança quase em tempo real. O Debezium é o nome mais comum. &lt;em&gt;Quando usar no lugar do relay por polling:&lt;/em&gt; quando o atraso do intervalo de consulta não cabe, ou quando o volume torna as consultas caras. &lt;em&gt;O que custa:&lt;/em&gt; mais uma peça de infraestrutura para operar e monitorar. Por isso o polling, que funciona com qualquer banco SQL, costuma ser o ponto de partida.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Event sourcing&lt;/strong&gt;: em vez de guardar o estado atual e emitir eventos, você guarda só a sequência de eventos e calcula o estado a partir dela. Resolve a escrita dupla entre estado e eventos por eliminação: gravar um evento é uma operação só. &lt;em&gt;Atenção:&lt;/em&gt; não elimina a chamada ao adquirente; o efeito externo continua precisando da intenção registrada antes. &lt;em&gt;Quando aparece:&lt;/em&gt; quando o histórico completo é requisito de negócio, o que é comum em domínio financeiro. &lt;em&gt;O que custa:&lt;/em&gt; muda o modelo de dados inteiro e dificulta consultas (em geral exige CQRS), então é decisão de arquitetura, não ajuste pontual. O post &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/&quot;&gt;Arquitetura de ledger&lt;/a&gt; mostra esse modelo, e a conciliação, aplicada a saldos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;6-decisões-que-o-desenho-deixa-com-você&quot;&gt;6. Decisões que o desenho deixa com você&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Relay parado em silêncio.&lt;/strong&gt; A métrica certa não é “o relay está rodando”, é o atraso: a idade do evento mais antigo não publicado (&lt;code&gt;min(criado_em)&lt;/code&gt; onde &lt;code&gt;publicado_em IS NULL&lt;/code&gt;), com alerta acima de alguns segundos. Relay vivo com fila crescendo é relay parado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quanto tempo um PENDENTE pode ficar.&lt;/strong&gt; Defina o prazo (minutos, não horas), rode a conciliação em intervalo menor que ele e exponha a contagem de PENDENTE acima do prazo como métrica. Um PENDENTE velho é dinheiro em lugar desconhecido.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O adquirente responde “não sei”.&lt;/strong&gt; Não adivinhe. A cobrança fica PENDENTE, a consulta se repete com espera crescente e, passado um prazo de negócio, entra a regra combinada: cancelar com a mesma chave, se a API permitir, ou escalar para tratamento manual. O que não pode é virar CAPTURADO ou FALHOU sem confirmação.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A tabela outbox cresce sem parar.&lt;/strong&gt; Evento publicado é lixo depois de alguns dias: um job apaga (ou move para arquivo) as linhas com &lt;code&gt;publicado_em&lt;/code&gt; mais antigo que N dias; em volume alto, particione por dia e solte a partição inteira.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conciliação como CronJob.&lt;/strong&gt; Se ela roda como &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/kubernetes-cronjob-concorrencia/&quot;&gt;CronJob no Kubernetes&lt;/a&gt;, &lt;code&gt;concurrencyPolicy: Forbid&lt;/code&gt; evita duas execuções sobrepostas, e o &lt;code&gt;SKIP LOCKED&lt;/code&gt; da consulta acima faz com que, mesmo que se sobreponham, cada uma pegue linhas diferentes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Polling ou CDC.&lt;/strong&gt; Comece pelo polling: funciona com qualquer banco SQL e sem peça nova. Troque por CDC quando o atraso do intervalo não couber no requisito ou quando as consultas ao outbox pesarem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AWS Prescriptive Guidance — &lt;a href=&quot;https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html&quot;&gt;Transactional outbox pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Confluent — &lt;a href=&quot;https://www.confluent.io/blog/dual-write-problem/&quot;&gt;Understanding the Dual-Write Problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;microservices.io — &lt;a href=&quot;https://microservices.io/patterns/data/transactional-outbox.html&quot;&gt;Pattern: Transactional outbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;microservices.io — &lt;a href=&quot;https://microservices.io/patterns/data/polling-publisher.html&quot;&gt;Pattern: Polling publisher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;microservices.io — &lt;a href=&quot;https://microservices.io/patterns/data/event-sourcing.html&quot;&gt;Pattern: Event sourcing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Debezium — &lt;a href=&quot;https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/&quot;&gt;Reliable Microservices Data Exchange With the Outbox Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Brandur Leach — &lt;a href=&quot;https://brandur.org/idempotency-keys&quot;&gt;Implementing Stripe-like Idempotency Keys in Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stripe — &lt;a href=&quot;https://docs.stripe.com/api/idempotent_requests&quot;&gt;Idempotent requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/sql-select.html&quot;&gt;SELECT: cláusula de trava (&lt;code&gt;FOR UPDATE SKIP LOCKED&lt;/code&gt;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/wal-intro.html&quot;&gt;Write-Ahead Logging (WAL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL — &lt;a href=&quot;https://www.postgresql.org/docs/current/sql-prepare-transaction.html&quot;&gt;PREPARE TRANSACTION&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Wikipedia — &lt;a href=&quot;https://en.wikipedia.org/wiki/Two-phase_commit_protocol&quot;&gt;Two-phase commit protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kubernetes — &lt;a href=&quot;https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/&quot;&gt;Assign Memory Resources to Containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kubernetes — &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination&quot;&gt;Pod Lifecycle: Termination of Pods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Arquitetura de Software</category><category>Pagamentos</category><category>Mensageria</category><category>Banco de Dados</category></item><item><title>Chave de idempotência — como impedir a cobrança duplicada no retry</title><link>https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/</guid><description>Por que consultar antes de gravar não impede que um retry cobre o cliente duas vezes, e como resolver com chave de idempotência, restrição única e resposta guardada. Com SQL testado no PostgreSQL.</description><pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;mark class=&quot;caneta-marca&quot;&gt;Um timeout não diz se a operação aconteceu.&lt;/mark&gt; Quando o app reenvia uma cobrança depois de um timeout, o serviço precisa reconhecer a repetição e não cobrar de novo. Parece simples, mas a solução mais intuitiva, consultar antes de gravar, falha justamente quando o serviço roda em várias instâncias. Este post mostra onde ela falha e o desenho que funciona: uma &lt;strong&gt;chave de idempotência&lt;/strong&gt; gerada pelo cliente, uma &lt;strong&gt;restrição única&lt;/strong&gt; no banco e a &lt;strong&gt;resposta guardada&lt;/strong&gt;, com SQL testado no PostgreSQL e os cuidados de produção.&lt;/p&gt;
&lt;h2 id=&quot;1-o-que-o-timeout-não-diz&quot;&gt;1. O que o timeout não diz&lt;/h2&gt;
&lt;p&gt;O app do cliente envia uma requisição de cobrança de R$ 250 para o serviço de autorização. A resposta não chega a tempo e a requisição estoura o timeout. Do lado do cliente, não dá para saber o que aconteceu: o servidor pode ter cobrado, pode ainda estar processando ou pode nem ter recebido o pedido. Então o app reenvia.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Animação: a resposta do serviço se perde no caminho e o app, sem saber, envia o pedido de novo.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;A animação está no site.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;O serviço roda em várias instâncias atrás de um load balancer. O reenvio pode cair numa instância diferente da primeira, e pode chegar enquanto a primeira ainda está trabalhando.&lt;/p&gt;
&lt;p&gt;O nome da propriedade que falta é &lt;strong&gt;idempotência&lt;/strong&gt;: uma operação é idempotente quando repeti-la tem o mesmo efeito que executá-la uma vez. A especificação do HTTP (RFC 9110) classifica GET, PUT e DELETE como idempotentes por definição; &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;POST não é&lt;/span&gt;. Uma cobrança é um POST, e cada repetição sem proteção vira uma cobrança nova.&lt;/p&gt;
&lt;p&gt;O que o cenário deixa em aberto, e que muda o desenho: o volume, se o cliente controla o reenvio, por quanto tempo a garantia precisa valer e o que acontece se o reenvio vier no dia seguinte.&lt;/p&gt;
&lt;h2 id=&quot;2-por-que-consultar-antes-de-gravar-não-basta&quot;&gt;2. Por que consultar antes de gravar não basta&lt;/h2&gt;
&lt;p&gt;A primeira ideia que aparece é verificar antes de gravar: o serviço consulta a tabela procurando uma cobrança com o mesmo número de pedido; se já existir, devolve a que existe; se não existir, insere e captura.&lt;/p&gt;
&lt;p&gt;A ideia está certa: reconhecer o pedido repetido e não cobrar de novo. O problema é &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;&lt;strong&gt;onde&lt;/strong&gt;&lt;/span&gt; a verificação acontece.&lt;/p&gt;
&lt;p&gt;Consultar e depois gravar são duas operações separadas, e entre elas existe uma janela, curta, mas real. Se a requisição original e o reenvio caem em instâncias diferentes ao mesmo tempo, as duas consultam antes de qualquer uma gravar, as duas encontram a &lt;span class=&quot;caneta caneta-liga&quot;&gt;tabela vazia e as duas cobram&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Esse defeito tem nome: &lt;strong&gt;condição de corrida do tipo verificar-e-agir&lt;/strong&gt; (&lt;em&gt;check-then-act&lt;/em&gt;). A decisão foi tomada com base num estado que mudou antes da ação. Na forma mais geral, é catalogada como TOCTOU (&lt;em&gt;time-of-check to time-of-use&lt;/em&gt;, CWE-367), e aparece em reserva de estoque, cadastro por e-mail, débito de saldo e no clássico “verifica se o arquivo existe antes de criar”.&lt;/p&gt;
&lt;div class=&quot;caneta-margem caneta-exclamacao&quot;&gt;&lt;p&gt;Isso dificilmente aparece em teste local, onde as requisições costumam chegar em sequência. Aparece em produção, no pico, quando o volume aumenta a chance de as duas coincidirem. O cenário é fácil de reproduzir no PostgreSQL: duas conexões simultâneas que consultam, esperam um segundo e inserem acabam gravando as duas.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/retry-cobranca-duplicada.svg&quot; alt=&quot;Diagrama: a requisição original e o reenvio caem em instâncias diferentes, as duas consultam antes de qualquer uma gravar e o cliente é cobrado duas vezes&quot;/&gt;&lt;/p&gt;
&lt;h2 id=&quot;3-gravar-primeiro-e-deixar-o-banco-recusar&quot;&gt;3. Gravar primeiro e deixar o banco recusar&lt;/h2&gt;
&lt;p&gt;A garantia precisa estar em quem consegue decidir sozinho, sem janela: &lt;strong&gt;o banco&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;São três peças:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chave de idempotência&lt;/strong&gt;: um identificador que o cliente gera uma vez por intenção de cobrança e repete em todas as tentativas dessa mesma intenção, normalmente num cabeçalho &lt;code&gt;Idempotency-Key&lt;/code&gt;. A Stripe recomenda um UUID v4 ou outro valor aleatório com entropia suficiente para não colidir, e sem dados pessoais. O id do pedido só serve como chave se cada pedido puder ser cobrado uma única vez; se o mesmo pedido pode ter cobranças legítimas separadas, a chave precisa identificar a cobrança, não o pedido. A mesma técnica vale para webhooks, APIs públicas de pagamento e comandos consumidos de fila.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restrição única&lt;/strong&gt; (&lt;code&gt;UNIQUE&lt;/code&gt;) no banco sobre essa chave. É ela que transforma “duas gravações” em “uma gravação e uma recusa”. É a integridade do banco no lugar de coordenação na aplicação: a decisão fica atômica porque acontece dentro da própria escrita, o mesmo mecanismo que garante slug de URL, número de matrícula e qualquer regra do tipo “só pode existir um”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resposta guardada&lt;/strong&gt;: a primeira tentativa salva o que respondeu. As seguintes, ao esbarrar na restrição, leem e devolvem exatamente a mesma resposta.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A ordem se inverte:&lt;/p&gt;
&lt;blockquote class=&quot;frase-destaque&quot; data-frase-destaque&gt;&lt;p&gt;&lt;span class=&quot;palavra&quot;&gt;Em&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;vez&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;de&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;verificar&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;depois&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;gravar,&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;você&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;grava&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;deixa&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;banco&lt;/span&gt; &lt;span class=&quot;palavra&quot;&gt;recusar.&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;A janela some porque &lt;mark class=&quot;caneta-marca&quot;&gt;verificar e gravar passam a ser a mesma operação&lt;/mark&gt;. Aperte o play ou arraste sobre a lousa para ver os cinco passos, contados logo abaixo dela.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Diagrama: o app, o serviço, o adquirente e a tabela cobranca. A segunda tentativa, com a mesma chave, bate na restrição única e recebe a resposta guardada, sem nova cobrança.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;A linha do tempo interativa está no site.&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;O app pede a cobrança de R$ 250 e manda junto a chave de idempotência que ele gerou, &lt;code&gt;5b0e7a52…&lt;/code&gt;. A chave é a mesma em todas as tentativas desse pedido.&lt;/li&gt;
&lt;li&gt;Antes de cobrar, o serviço grava a chave na tabela &lt;code&gt;cobranca&lt;/code&gt;, que tem restrição &lt;code&gt;UNIQUE&lt;/code&gt; sobre ela. Quem grava primeiro fica com a chave, e o status começa como &lt;code&gt;PROCESSANDO&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;O serviço confirma o registro, cobra no adquirente e guarda a resposta junto da chave: &lt;code&gt;CAPTURADA&lt;/code&gt;, com o &lt;code&gt;201&lt;/code&gt; que devolveu ao app.&lt;/li&gt;
&lt;li&gt;A resposta se perde no caminho de volta. Para o app, é como se nada tivesse acontecido, então ele tenta de novo, com a mesma chave.&lt;/li&gt;
&lt;li&gt;O &lt;code&gt;INSERT&lt;/code&gt; da segunda tentativa bate na restrição &lt;code&gt;UNIQUE&lt;/code&gt;. Em vez de cobrar de novo, o serviço devolve a resposta que já estava guardada.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;na-prática-com-sql&quot;&gt;Na prática, com SQL&lt;/h3&gt;
&lt;p&gt;Uma tabela mínima no PostgreSQL:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:11&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;cobranca.sql&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TABLE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id              &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;GENERATED&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ALWAYS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AS&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;IDENTITY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;idempotency_key &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pedido_id       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;valor_centavos  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;bigint&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- PROCESSANDO, CAPTURADA ou RECUSADA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;resposta_http   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,              &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- status HTTP devolvido na primeira vez&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;resposta_corpo  jsonb,            &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;-- corpo devolvido na primeira vez&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;criada_em       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;timestamptz&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DEFAULT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CONSTRAINT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; uq_cobranca_idempotency_key &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UNIQUE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (idempotency_key)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Passo 1: registrar a tentativa antes de cobrar.&lt;/strong&gt; Toda requisição começa tentando inserir a chave, já com o status &lt;code&gt;PROCESSANDO&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca (idempotency_key, pedido_id, valor_centavos, &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5b0e7a52-3f1c-4d7e-9a61-2c8f0d4e7b13&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;123&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;25000&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;PROCESSANDO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line caneta-linhas-inicio&quot; style=&quot;--caneta-n:2&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ON&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CONFLICT (idempotency_key) DO NOTHING&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;RETURNING id;&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-codigo&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;1 linha: a primeira; 0: repetição&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code&gt;ON CONFLICT ... DO NOTHING&lt;/code&gt; faz o banco ignorar a inserção se a chave já existir, em vez de lançar erro. Como o &lt;code&gt;RETURNING&lt;/code&gt; só devolve linhas de fato inseridas, o resultado responde à pergunta sem janela nenhuma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 linha&lt;/strong&gt;: esta requisição é a primeira. Confirme a transação (&lt;em&gt;commit&lt;/em&gt;), chame o adquirente e grave o resultado (passo 2).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;0 linhas&lt;/strong&gt;: a chave já existia. Não cobre; leia o registro (passo 3).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sem o &lt;code&gt;ON CONFLICT&lt;/code&gt;, a segunda inserção falha com &lt;code&gt;duplicate key value violates unique constraint &amp;quot;uq_cobranca_idempotency_key&amp;quot;&lt;/code&gt;. Funciona do mesmo jeito, só que a aplicação precisa tratar a exceção.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Passo 2: guardar a resposta&lt;/strong&gt; depois que o adquirente responder:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UPDATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SET&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;CAPTURADA&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;resposta_http  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;201&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;resposta_corpo &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;{&amp;quot;cobranca_id&amp;quot;: 1, &amp;quot;status&amp;quot;: &amp;quot;CAPTURADA&amp;quot;}&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; idempotency_key &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5b0e7a52-3f1c-4d7e-9a61-2c8f0d4e7b13&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Passo 3: responder a uma repetição.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title sem-titulo&quot; style=&quot;--linhas:3&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SELECT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;, pedido_id, valor_centavos, resposta_http, resposta_corpo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cobranca&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;WHERE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; idempotency_key &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;5b0e7a52-3f1c-4d7e-9a61-2c8f0d4e7b13&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Se &lt;code&gt;pedido_id&lt;/code&gt; ou &lt;code&gt;valor_centavos&lt;/code&gt; forem diferentes dos da requisição atual, a chave foi reaproveitada para outra operação. Recuse: o rascunho da IETF para o cabeçalho &lt;code&gt;Idempotency-Key&lt;/code&gt; sugere &lt;span class=&quot;caneta caneta-circulo longo&quot;&gt;&lt;code&gt;422 Unprocessable Content&lt;/code&gt;&lt;/span&gt;, e a Stripe também devolve erro quando os parâmetros não batem com os da requisição original.&lt;/li&gt;
&lt;li&gt;Se o status for &lt;code&gt;PROCESSANDO&lt;/code&gt;, a primeira tentativa ainda não terminou. Responda &lt;code&gt;409 Conflict&lt;/code&gt; para o cliente tentar de novo mais tarde; é o que o mesmo rascunho propõe.&lt;/li&gt;
&lt;li&gt;Se já houver resposta guardada, devolva &lt;code&gt;resposta_http&lt;/code&gt; e &lt;code&gt;resposta_corpo&lt;/code&gt; como estão.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cuidados&quot;&gt;Cuidados&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Confirme o registro antes de chamar o adquirente.&lt;/strong&gt; Se a inserção e a chamada externa ficarem na &lt;span class=&quot;caneta caneta-nota&quot;&gt;&lt;span class=&quot;caneta-alvo&quot;&gt;mesma transação&lt;/span&gt;&lt;span class=&quot;caneta-escrita caneta-nota-texto&quot;&gt;&lt;span class=&quot;caneta-sr&quot;&gt; (nota: &lt;/span&gt;conexões presas!&lt;span class=&quot;caneta-sr&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; aberta, a segunda inserção com a mesma chave não recusa na hora: o PostgreSQL faz quem tenta inserir esperar até a outra transação terminar. Num teste com PostgreSQL 17, o reenvio ficou parado os dois segundos que a primeira transação levou, e só então recebeu 0 linhas. Sob carga, isso vira conexões presas e fila, e o cliente nunca vê o &lt;code&gt;PROCESSANDO&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Um &lt;code&gt;PROCESSANDO&lt;/code&gt; pode ficar órfão.&lt;/strong&gt; Se o processo morrer entre o commit e a resposta do adquirente, sobra um registro sem desfecho. Descobrir se a cobrança passou é trabalho de conciliação, tema do post &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decida por quanto tempo a chave vale.&lt;/strong&gt; A Stripe pode remover chaves com pelo menos 24 horas de idade; uma chave reutilizada depois disso gera uma requisição nova. O rascunho da IETF deixa o prazo para cada API definir e publicar na documentação. Prazo mais longo protege reenvios tardios e custa armazenamento; qualquer que seja, precisa estar escrito no contrato da API, porque o cliente que reenvia no dia seguinte vai descobrir na prática.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decida se erro também fica guardado.&lt;/strong&gt; A Stripe guarda o status e o corpo da primeira resposta &lt;span class=&quot;caneta caneta-ondulado&quot;&gt;seja sucesso ou falha&lt;/span&gt;, inclusive erros &lt;code&gt;500&lt;/code&gt;. Com isso, uma nova tentativa depois de uma recusa exige chave nova, porque é uma nova intenção.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;4-o-que-a-restrição-única-não-cobre&quot;&gt;4. O que a restrição única não cobre&lt;/h2&gt;
&lt;p&gt;A chave resolve o caso em que a decisão cabe numa chave: “esta intenção já foi processada?”. Três situações vizinhas pedem outra ferramenta.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A decisão depende do valor lido.&lt;/strong&gt; Débito de saldo, controle de estoque, qualquer “leu, calculou, gravou”: não existe chave que expresse “o saldo ainda é o que eu li”. As alternativas são o bloqueio pessimista (&lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt;, que trava a linha e faz os concorrentes esperarem) e o otimista (uma coluna de versão, e só grava quem leu a versão atual). Os dois precisam de uma linha que já exista; aqui a cobrança ainda não existe, então seria preciso travar outra linha, como a do pedido, o que é mais um motivo para preferir a restrição única quando ela basta. Os dois são detalhados em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/&quot;&gt;Bloqueio otimista e pessimista&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O efeito externo antes do registro.&lt;/strong&gt; A chave só protege &lt;span class=&quot;caneta caneta-duplo&quot;&gt;o que chegou a ser gravado&lt;/span&gt;. Se a captura no adquirente passar e a gravação da resposta falhar, ou se o processo morrer antes de gravar qualquer coisa, sobra dinheiro cobrado sem registro. O desenho que fecha esse buraco, gravar a intenção antes de causar o efeito, está em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A cobrança vira um evento numa fila.&lt;/strong&gt; Quando o pedido chega de um tópico em vez de uma chamada síncrona, a repetição é ainda mais certa: a garantia padrão do Kafka, da fila Standard do SQS e do RabbitMQ com confirmações (&lt;em&gt;acks&lt;/em&gt;) é &lt;strong&gt;entrega pelo menos uma vez&lt;/strong&gt; (&lt;em&gt;at-least-once&lt;/em&gt;). “Exatamente uma vez” existe só em escopos limitados, como a deduplicação de 5 minutos das filas FIFO do SQS ou as transações dentro do próprio Kafka; quando o efeito sai para um sistema externo, a documentação do Kafka lembra que o destino precisa cooperar. Na prática, entrega-se pelo menos uma vez e o consumidor é idempotente, com a mesma tabela e a mesma restrição única deste post, usando o id da mensagem (ou a chave que veio dentro dela) como chave de idempotência. É por isso que idempotência e mensageria andam juntas.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-regra-prática&quot;&gt;5. Regra prática&lt;/h2&gt;
&lt;p&gt;A mesma falha de rede, com e sem a chave de idempotência. Avance no tempo e compare as duas linhas.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Linha do tempo comparando o reenvio com e sem chave de idempotência: sem a chave, o cliente é cobrado duas vezes; com a chave, a restrição única devolve a resposta guardada.&lt;/em&gt; &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;A linha do tempo interativa está no site.&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A chave é gerada pelo &lt;strong&gt;cliente&lt;/strong&gt;, uma por intenção, e repetida em todas as tentativas dessa intenção. Id de pedido só serve se o pedido só puder ser cobrado uma vez.&lt;/li&gt;
&lt;li&gt;Quem decide é o &lt;strong&gt;banco&lt;/strong&gt;: &lt;code&gt;UNIQUE&lt;/code&gt; na chave e &lt;code&gt;INSERT ... ON CONFLICT DO NOTHING RETURNING&lt;/code&gt; antes de qualquer efeito externo. Nunca &lt;span class=&quot;caneta caneta-riscado&quot;&gt;&lt;s&gt;“consulta, depois grava”&lt;/s&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confirme&lt;/strong&gt; o registro antes de chamar o adquirente; a chamada externa fica fora da transação.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;primeira resposta fica guardada&lt;/strong&gt; e é devolvida igual nas repetições; parâmetros diferentes com a mesma chave são recusados.&lt;/li&gt;
&lt;li&gt;O &lt;strong&gt;prazo da chave&lt;/strong&gt; e o tratamento de erro são decisões de contrato: escolha, documente e meça o armazenamento.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;IETF — &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc9110.html#section-9.2.2&quot;&gt;RFC 9110: HTTP Semantics, seção 9.2.2 (métodos idempotentes)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IETF — &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-httpapi-idempotency-key-header/&quot;&gt;The Idempotency-Key HTTP Header Field (Internet-Draft)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stripe — &lt;a href=&quot;https://docs.stripe.com/api/idempotent_requests&quot;&gt;Idempotent requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL 17 — &lt;a href=&quot;https://www.postgresql.org/docs/17/index-unique-checks.html&quot;&gt;Index Uniqueness Checks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL 17 — &lt;a href=&quot;https://www.postgresql.org/docs/17/sql-insert.html&quot;&gt;INSERT (ON CONFLICT e RETURNING)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PostgreSQL 17 — &lt;a href=&quot;https://www.postgresql.org/docs/17/ddl-constraints.html&quot;&gt;Constraints (Unique Constraints)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MITRE — &lt;a href=&quot;https://cwe.mitre.org/data/definitions/367.html&quot;&gt;CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Apache Kafka — &lt;a href=&quot;https://kafka.apache.org/42/design/design/&quot;&gt;Design: Message Delivery Semantics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues-at-least-once-delivery.html&quot;&gt;Amazon SQS at-least-once delivery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues-exactly-once-processing.html&quot;&gt;Exactly-once processing in Amazon SQS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RabbitMQ — &lt;a href=&quot;https://www.rabbitmq.com/docs/reliability&quot;&gt;Reliability Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ByteByteGo — &lt;a href=&quot;https://bytebytego.com/guides/how-to-avoid-double-payment/&quot;&gt;How to Avoid Double Payment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Arquitetura de Software</category><category>Pagamentos</category><category>Idempotência</category><category>Banco de Dados</category></item><item><title>Arquitetura de ledger — partidas dobradas, saldos e conciliação</title><link>https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/</guid><description>O que 12 artigos ensinam sobre ledgers de grau financeiro: registro append-only, double-entry garantido pelo banco, saldos materializados, idempotência e conciliação como entregável de engenharia — com exemplos em Java.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Todo sistema que movimenta valor — dinheiro, créditos, pontos — esbarra nos mesmos problemas: como garantir que nada seja criado nem destruído por acidente, como responder “qual era o saldo naquela data” e como perceber quando o número exibido divergiu da verdade. Os artigos resumidos aqui chegam à mesma resposta: &lt;strong&gt;ledger append-only + saldo materializado + conciliação&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Este post resume 12 artigos sobre o assunto — as séries &lt;em&gt;How to Scale a Ledger&lt;/em&gt; e &lt;em&gt;Accounting for Developers&lt;/em&gt;, da Modern Treasury, e mais três textos independentes —, com os exemplos de código convertidos para Java. Cada seção traz a ideia central do artigo, os pontos importantes e o link para o original. Se contabilidade é novidade para você, vale ler antes as seções 8 a 10 (os fundamentos) e depois voltar ao começo.&lt;/p&gt;
&lt;p&gt;O modelo que todos compartilham tem três peças: a &lt;strong&gt;account&lt;/strong&gt; (conta), a &lt;strong&gt;transaction&lt;/strong&gt; (o movimento completo) e as &lt;strong&gt;entries&lt;/strong&gt; (os lançamentos de débito e crédito que compõem a transaction):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/modelo-account-transaction-entry.svg&quot; alt=&quot;O modelo central do ledger: Transaction agrupa entries imutáveis que debitam e creditam accounts&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;vocabulário-mínimo&quot;&gt;Vocabulário mínimo&lt;/h2&gt;
&lt;p&gt;Os termos abaixo aparecem o tempo todo no post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ledger (livro-razão):&lt;/strong&gt; o registro de todos os movimentos de valor de um sistema.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double-entry (partidas dobradas):&lt;/strong&gt; todo movimento tem pelo menos um débito e um crédito, e a soma dos débitos é igual à soma dos créditos. Dinheiro sempre sai de algum lugar e entra em outro.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Débito e crédito:&lt;/strong&gt; não significam “tira” e “põe”. O efeito de cada um depende do tipo da conta (a &lt;em&gt;normalidade&lt;/em&gt;, explicada nas seções 3 e 8).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Append-only:&lt;/strong&gt; só se acrescentam registros; nada é alterado nem apagado. Um erro se corrige com um novo lançamento, que compensa o anterior.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saldo materializado:&lt;/strong&gt; saldo pré-calculado e guardado para leitura rápida, mas sempre derivado dos lançamentos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drift:&lt;/strong&gt; divergência entre o saldo guardado e a soma dos lançamentos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conciliação:&lt;/strong&gt; comparar dois registros que deveriam bater (saldo guardado × lançamentos, ou ledger × extrato do banco) e tratar as diferenças.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idempotência:&lt;/strong&gt; repetir a mesma requisição não repete o efeito. O tema tem post próprio: &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/cobranca-duplicada-no-retry/&quot;&gt;Cobrança duplicada no retry&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Liquidação (settlement):&lt;/strong&gt; o momento em que o dinheiro efetivamente muda de mãos, em geral depois da autorização.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;1-ledger-confiável-em-sistema-event-driven-sem-transações-gigantes&quot;&gt;1. Ledger confiável em sistema event-driven, sem transações gigantes&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; como construir um ledger de grau financeiro num sistema distribuído e orientado a eventos &lt;strong&gt;sem&lt;/strong&gt; envolver cada operação numa transação de banco gigante. A consistência vem de concorrência otimista, particionamento e restrições de unicidade — não de locks globais.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Event sourcing:&lt;/strong&gt; cada mudança vira um evento imutável (depósito, saque, bloqueio de valor). Em vez de guardar só o saldo final, você guarda todos os eventos, e o saldo pode ser reconstruído a partir deles. Isso dá trilha de auditoria completa e permite reprocessar tudo (&lt;em&gt;replay&lt;/em&gt;) se a lógica mudar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CQRS (separação entre comando e consulta):&lt;/strong&gt; o lado de comando recebe “Sacar $30” e, se o comando for válido, emite o evento &lt;code&gt;FundsWithdrawn&lt;/code&gt;. O lado de consulta assina os eventos e atualiza um &lt;em&gt;read model&lt;/em&gt; (uma tabela otimizada para leitura, como &lt;code&gt;account_balances&lt;/code&gt;). A consulta de saldo lê essa tabela em vez de reprocessar todos os eventos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O problema de concorrência:&lt;/strong&gt; dois eventos quase simultâneos na mesma conta (depósito de $50 e saque de $30) podem ler dados desatualizados e perder ou contar dinheiro em dobro se não houver controle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Três técnicas para resolver sem transação gigante:&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Controle de concorrência otimista (OCC):&lt;/strong&gt; cada conta — o &lt;em&gt;aggregate&lt;/em&gt;, no vocabulário de DDD — tem uma &lt;code&gt;version&lt;/code&gt; inteira. Ao gravar um evento, você informa a versão que leu; se ela mudou porque outro evento entrou antes, a gravação falha e você recarrega o estado e tenta de novo (&lt;em&gt;compare-and-swap&lt;/em&gt;). O assunto é aprofundado em &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/bloqueio-otimista-e-pessimista/&quot;&gt;Bloqueio otimista e pessimista&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Particionamento por conta:&lt;/strong&gt; sistemas como o Kafka particionam as mensagens por uma chave, aqui o &lt;code&gt;account_id&lt;/code&gt;. Cada partição é consumida em sequência por uma única thread, o que garante ordem serial dentro da mesma conta e paralelismo entre contas diferentes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restrição de unicidade&lt;/strong&gt; em &lt;code&gt;(aggregate_id, version)&lt;/code&gt;: o próprio banco rejeita a segunda inserção com a mesma versão. É a salvaguarda do &lt;em&gt;compare-and-swap&lt;/em&gt; no nível do banco.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idempotência no replay:&lt;/strong&gt; ao reprocessar eventos, guarde o &lt;code&gt;aggregate_id&lt;/code&gt; e a versão já aplicados; se o evento já foi aplicado, pule. Assim nada é contado duas vezes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saldo bloqueado × disponível:&lt;/strong&gt; ledgers reais precisam de estados como valores reservados (por exemplo, a autorização de um cartão, que bloqueia o valor antes de liquidar). Modele eventos &lt;code&gt;FundsHeld&lt;/code&gt;, &lt;code&gt;FundsReleased&lt;/code&gt; e &lt;code&gt;FundsSettled&lt;/code&gt; e mantenha uma projeção com &lt;code&gt;held_balance&lt;/code&gt; e &lt;code&gt;available_balance&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O event store se resume a uma tabela &lt;code&gt;events&lt;/code&gt; (o artigo usa MySQL; aqui, a versão em PostgreSQL):&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:9&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;events.sql&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;SQL&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TABLE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; events (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;id           &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BIGSERIAL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aggregate_id &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;)  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;INT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;event_type   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VARCHAR&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;255&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;payload      JSONB        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;created_at   &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TIMESTAMPTZ&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NOT NULL&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;UNIQUE&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; (aggregate_id, &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O &lt;code&gt;append&lt;/code&gt; confere a versão esperada e grava os eventos numa transação curta, que envolve só os eventos daquela conta. A conferência sozinha não basta: dois escritores podem ler a mesma versão ao mesmo tempo. Quem fecha essa brecha é a restrição de unicidade — o segundo &lt;code&gt;INSERT&lt;/code&gt; falha com o código &lt;code&gt;23505&lt;/code&gt; (&lt;code&gt;unique_violation&lt;/code&gt;) e vira um conflito de versão:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:60&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;EventStore.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Event store com checagem de versão esperada (compare-and-swap)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;EventStore&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; UNIQUE_VIOLATION &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;23505&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// SQLSTATE do PostgreSQL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;final&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DataSource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; EventStore&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DataSource&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;dataSource &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Versão atual (maior version) de uma conta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; getCurrentVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Connection&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SQLException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sql &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;SELECT COALESCE(MAX(version), 0) FROM events WHERE aggregate_id = ?&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PreparedStatement&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; stmt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;prepareStatement&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ResultSet&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; rs &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;executeQuery&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; rs&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; rs&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getInt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Append com verificação de versão esperada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; append&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; expectedVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DomainEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throws&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SQLException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Connection&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conn &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getConnection&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setAutoCommit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// transação curta: só os eventos desta conta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 1) Checa a versão mais recente e compara com a esperada&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; currentVersion &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; getCurrentVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentVersion &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; expectedVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; VersionConflictException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Version conflict! Expected &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; expectedVersion &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;, got &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; currentVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 2) Insere cada evento com a versão seguinte&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; insert &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;INSERT INTO events &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;(aggregate_id, version, event_type, payload, created_at) &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;VALUES (?, ?, ?, CAST(? AS JSONB), NOW())&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PreparedStatement&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; stmt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;prepareStatement&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DomainEvent&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; event &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setInt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;currentVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; event&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getClass&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getName&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; event&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toPayloadJson&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;executeUpdate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;commit&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SQLException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;RuntimeException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;rollback&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// 3) Outro escritor gravou a mesma (aggregate_id, version) entre a leitura e o insert&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ex &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;instanceof&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;SQLException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sqlEx &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; UNIQUE_VIOLATION&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sqlEx&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getSQLState&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; VersionConflictException&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Version conflict on insert&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sqlEx&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Quem chama trata o conflito recarregando o estado e revalidando o comando — o saldo pode não ser mais suficiente depois do evento que entrou antes:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:23&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;WithdrawHandler.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Retry em caso de conflito de versão&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; handleWithdrawCommand&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; withdrawAmount&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;throws SQLException &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; attempt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; attempt&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Reconstrói o estado da conta a partir dos eventos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DomainEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; events &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; eventStore&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;loadEvents&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;AccountAggregate&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; aggregate &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; AccountAggregate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; expectedVersion &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; aggregate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// ex.: 5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Regra de negócio: recusa o saque se o saldo não for suficiente&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;DomainEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; newEvents &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; aggregate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;withdraw&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;withdrawAmount&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;eventStore&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;append&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; expectedVersion&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; newEvents&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;VersionConflictException&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Outro evento entrou antes: recarrega e revalida na próxima volta&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;attempt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MAX_ATTEMPTS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; ex&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://new2026.medium.com/building-a-reliable-ledger-in-an-event-sourced-system-without-big-db-transactions-879061a7ff87&quot;&gt;Building a Reliable Ledger in an Event-Sourced System Without Big DB Transactions&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;2-how-to-scale-a-ledger-part-i--por-que-usar-um-banco-de-ledger&quot;&gt;2. How to Scale a Ledger, Part I — por que usar um banco de ledger&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; toda empresa que move dinheiro em escala precisa de um ledger — um banco de dados double-entry — como fonte única da verdade, em vez de espalhar a lógica financeira pelos modelos de domínio (o objeto “pedido”, “corrida”, “reserva”).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Por que os modelos tradicionais falham em escala:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;as exigências de relatório e auditoria crescem (é preciso saber origem e destino de cada centavo);&lt;/li&gt;
&lt;li&gt;os dados ficam fragmentados entre vários serviços e produtos SaaS que não se integram;&lt;/li&gt;
&lt;li&gt;a performance degrada (jobs de repasse perdem o prazo, a checagem de autorização de cartão atrasa);&lt;/li&gt;
&lt;li&gt;cenários de falha (cobrança a mais, saldo insuficiente, fraude) ficam mais frequentes e difíceis de reverter.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modelo de dados central:&lt;/strong&gt; &lt;strong&gt;accounts&lt;/strong&gt; (porções separadas de valor), &lt;strong&gt;transactions&lt;/strong&gt; (eventos monetários atômicos) e &lt;strong&gt;entries&lt;/strong&gt; (os débitos e créditos individuais que compõem a transaction).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;As quatro garantias de um ledger escalável:&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Imutabilidade&lt;/strong&gt; — estados passados sempre podem ser recuperados; as mudanças são permanentes e consultáveis.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double-entry obrigatório&lt;/strong&gt; — não dá para mover dinheiro sem informar a origem e o destino.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Controle de concorrência&lt;/strong&gt; — o mesmo dinheiro não pode ser gasto duas vezes, mesmo com escritas paralelas ou fora de ordem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agregações eficientes&lt;/strong&gt; — somar eventos financeiros de um período é rápido.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O problema da “tradução”:&lt;/strong&gt; engenheiros de produto falam a língua do domínio (pedidos, corridas, reservas), mas precisam traduzi-la para a língua de finanças (débitos, créditos, ativos, passivos) — com eventos que chegam fragmentados, de APIs diferentes e de registros que mudam.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consequência real de erros:&lt;/strong&gt; um líder de produto de uma grande empresa de pagamentos contou que, todo mês, o time financeiro notava “alguns milhões de dólares” sumidos do ledger. O dinheiro continuava no banco; o que se perdia era a &lt;strong&gt;atribuição&lt;/strong&gt; (o registro de a quem ele pertence).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Por que não construir do zero:&lt;/strong&gt; um ledger double-entry performático e confiável leva anos de esforço e dezenas de engenheiros sênior; hoje há bancos de dados de ledger prontos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-i&quot;&gt;How to Scale a Ledger, Part I&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;3-part-ii--mapeando-eventos-financeiros&quot;&gt;3. Part II — mapeando eventos financeiros&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; detalha os três objetos centrais (account, entry, transaction), como mapear eventos financeiros reais neles e como calcular os diferentes tipos de saldo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dois princípios básicos:&lt;/strong&gt; todo evento monetário é registrado num modelo double-entry consistente, e &lt;strong&gt;todos os saldos&lt;/strong&gt; mostrados a usuários e sistemas são &lt;strong&gt;lidos desse modelo&lt;/strong&gt; (nunca de um campo mutável solto).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Account = porção separada de valor&lt;/strong&gt;, numa moeda. Ela deve informar três saldos:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Posted (lançado):&lt;/strong&gt; apenas o que já liquidou.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pending (pendente):&lt;/strong&gt; o que já liquidou mais o que deve liquidar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Available (disponível):&lt;/strong&gt; o que pode sair agora — desconta as saídas previstas e não conta as entradas ainda não liquidadas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O ciclo de vida de um cartão de crédito&lt;/strong&gt; ilustra como cada ação afeta esses saldos: compra de passagem (pendente), liquidação, pagamento da fatura, pré-autorização de hotel e sua liberação.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entry = registro imutável de movimento.&lt;/strong&gt; Saldos nunca são alterados diretamente; toda mudança entra como uma entry. Os campos centrais (&lt;code&gt;amount&lt;/code&gt;, &lt;code&gt;direction&lt;/code&gt;) são imutáveis; o único campo mutável é &lt;code&gt;discarded_at&lt;/code&gt;, usado só para substituir entries pendentes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Descartar × reverter:&lt;/strong&gt; só entries &lt;code&gt;pending&lt;/code&gt; podem ser substituídas; entries &lt;code&gt;posted&lt;/code&gt; e &lt;code&gt;archived&lt;/code&gt; são permanentes. Descartar a pendente, em vez de criar uma entry de reversão, mantém o histórico limpo — os débitos reais do cliente não se misturam com débitos criados só para reverter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Normalidade da conta (ponto-chave):&lt;/strong&gt; cada conta é &lt;strong&gt;debit normal&lt;/strong&gt; (usos de recursos: ativos e despesas — aumentam com débito) ou &lt;strong&gt;credit normal&lt;/strong&gt; (fontes de recursos: passivos, patrimônio líquido e receita — aumentam com crédito). Com números positivos e negativos, um depósito não conseguiria aumentar as duas contas envolvidas ao mesmo tempo, porque uma delas teria de ficar negativa para a soma fechar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cinco campos para calcular qualquer saldo:&lt;/strong&gt; &lt;code&gt;posted_debits&lt;/code&gt;, &lt;code&gt;posted_credits&lt;/code&gt;, &lt;code&gt;pending_debits&lt;/code&gt;, &lt;code&gt;pending_credits&lt;/code&gt; e &lt;code&gt;normal_balance&lt;/code&gt;. O ledger deve buscar esses cinco campos rapidamente e só calcular os saldos quando alguém pedir.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As fórmulas do artigo, em Java (lembrando que, no modelo da Modern Treasury, os totais &lt;code&gt;pending_*&lt;/code&gt; já incluem o que está &lt;code&gt;posted&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:36&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;BalanceCalculator.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;NormalBalance&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;CREDIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;DEBIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;BalanceCalculator&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Posted balance&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NormalBalance&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; normal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;normal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CREDIT &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;postedDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; DEBIT  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;postedCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Pending balance&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NormalBalance&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; normal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                     &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                     &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;normal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CREDIT &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pendingDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; DEBIT  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pendingCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Available balance&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; availableBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;NormalBalance&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; normal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;                                       &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; pendingDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;normal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; CREDIT &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pendingDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; DEBIT  &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; postedDebits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;subtract&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;pendingCredits&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-ii&quot;&gt;How to Scale a Ledger, Part II&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;4-part-iii--o-modelo-de-transaction&quot;&gt;4. Part III — o modelo de transaction&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; a &lt;strong&gt;transaction&lt;/strong&gt;, que agrupa as entries, é o que garante movimento de dinheiro atômico e obriga o double-entry. Sem ela, dá para deixar o ledger inconsistente registrando só parte de um movimento.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uma transaction garante:&lt;/strong&gt; &lt;strong&gt;atomicidade&lt;/strong&gt; (todas as entries têm sucesso ou falham juntas), &lt;strong&gt;consistência&lt;/strong&gt; (nada de mudanças parciais) e &lt;strong&gt;double-entry&lt;/strong&gt; (entries sempre balanceadas).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O risco sem transaction:&lt;/strong&gt; se a entry de débito grava, mas a de crédito falha (por exemplo, por um problema de rede), um lado foi debitado e o outro não recebeu nada — o dinheiro se perdeu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A API só deve permitir criar transactions, nunca entries avulsas.&lt;/strong&gt; Assim o cliente não consegue deixar um movimento pela metade; as entries são gerenciadas internamente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Três estados da transaction:&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pending&lt;/strong&gt; (estado inicial): grava débito e crédito como &lt;code&gt;pending&lt;/code&gt;, ainda não finalizados.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Posted&lt;/strong&gt; (finalizado): como entries são imutáveis, as pendentes são descartadas e novas entries &lt;code&gt;posted&lt;/code&gt; são criadas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Archived&lt;/strong&gt; (cancelado antes de ser lançado): só transactions pendentes podem ser arquivadas; as entries pendentes são descartadas e novas entries &lt;code&gt;archived&lt;/code&gt; são criadas, preservando o histórico do cancelamento.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tudo ou nada:&lt;/strong&gt; todas as entries não descartadas de uma transaction têm o mesmo status que ela, e por isso mudam de status juntas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-iii&quot;&gt;How to Scale a Ledger, Part III&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;5-part-iv--registrar--autorizar&quot;&gt;5. Part IV — registrar × autorizar&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; um ledger opera em dois modos. No &lt;strong&gt;recording&lt;/strong&gt; (registro), ele só anota o que já aconteceu em outros sistemas; no &lt;strong&gt;authorizing&lt;/strong&gt; (autorização), aprova ou nega transactions ativamente. A maioria das implementações só escala bem em um dos dois; o ideal é escolher o modo no nível da entry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recording:&lt;/strong&gt; alto volume de escrita (milhares por segundo ou mais), processamento assíncrono (as leituras podem ficar alguns segundos defasadas, com consistência eventual) e suporte a consultas complexas. Aqui o ledger &lt;strong&gt;não é&lt;/strong&gt; a fonte da verdade — ele reflete o que já aconteceu em outro lugar (banco, processadora de cartão).
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;effective_at&lt;/code&gt;:&lt;/strong&gt; data e hora informadas pelo cliente para retroagir a transaction ao momento em que o dinheiro realmente se moveu. Todas as entries herdam o &lt;code&gt;effective_at&lt;/code&gt; da transaction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Versões do saldo da conta:&lt;/strong&gt; como saldos passados podem mudar, cada conta tem uma &lt;code&gt;version&lt;/code&gt; incrementada sempre que uma entry é criada ou modificada. Cada entry guarda o &lt;code&gt;account_version&lt;/code&gt; correspondente, o que permite saber exatamente quais entries compõem um saldo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Casos de uso:&lt;/strong&gt; exibir detalhes da conta, repasses (payouts), gestão de empréstimos, cripto.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authorizing:&lt;/strong&gt; consistência &lt;em&gt;read-after-write&lt;/em&gt; (a leitura logo após a escrita já enxerga o novo saldo), volume menor (a performance degrada perto de 100 entries por segundo numa mesma conta), verificações de saldo e controle de concorrência. É o modo para mover dinheiro em tempo real, validando se há saldo — carteiras digitais e autorização de cartão.
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version locking:&lt;/strong&gt; o cliente envia a versão da conta junto com o pedido, e o ledger rejeita se a versão no banco for outra (bloqueio otimista). O algoritmo: inicia a transação de banco → grava a entry → atualiza a versão da conta com condição na versão atual → faz commit se a atualização aconteceu, senão rollback.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Balance locking:&lt;/strong&gt; o version locking sofre com &lt;em&gt;hot accounts&lt;/em&gt; — contas com tanta escrita que a versão muda antes de o cliente conseguir usá-la. A alternativa é condicionar a escrita ao &lt;strong&gt;saldo&lt;/strong&gt; (por exemplo, &lt;code&gt;gte: 0&lt;/code&gt;: só grava se o saldo não ficar negativo). No exemplo do artigo, o mesmo resultado sai em 2 chamadas em vez de 6, e a API expressa melhor a intenção.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modo misto (o ideal):&lt;/strong&gt; decidir entre recording e authorizing &lt;strong&gt;por entry&lt;/strong&gt;, não por conta. Numa autorização de cartão, a entry da conta do cliente precisa de balance lock e consistência forte, enquanto a entry da conta da processadora (liquidada uma vez por dia) pode ter consistência eventual e alto volume. As duas continuam atômicas na mesma transaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-iv&quot;&gt;How to Scale a Ledger, Part IV&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;6-part-v--imutabilidade-e-double-entry-a-fundo&quot;&gt;6. Part V — imutabilidade e double-entry a fundo&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; aprofunda duas das quatro garantias: imutabilidade (qualquer estado passado do ledger pode ser reconstruído) e double-entry (dinheiro não pode ser criado nem destruído).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Imutabilidade apesar de campos mutáveis:&lt;/strong&gt; o saldo das accounts muda, transactions passam de pending para posted ou archived, entries podem ser descartadas — mas tudo é construído sobre um &lt;strong&gt;log append-only imutável&lt;/strong&gt;. Nada é apagado de fato.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Como consultar estados passados:&lt;/strong&gt; as entries de uma conta num dado instante são as que têm &lt;code&gt;effective_at&lt;/code&gt; menor ou igual a esse instante e não tinham sido descartadas até lá (consulta abaixo).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Versões para precisão:&lt;/strong&gt; só a data e hora não bastam, porque várias entries podem ter o mesmo &lt;code&gt;effective_at&lt;/code&gt; ou &lt;code&gt;discarded_at&lt;/code&gt;. As versões da conta gravadas nas entries dizem exatamente quais entries formam um saldo, e as versões passadas da transaction permitem reconstruir estados anteriores.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Log de auditoria:&lt;/strong&gt; além do estado, registre &lt;strong&gt;o que&lt;/strong&gt; mudou, &lt;strong&gt;quem&lt;/strong&gt; mudou e &lt;strong&gt;quando&lt;/strong&gt; (várias chaves de API, usuários internos pelo painel administrativo). O artigo recomenda um log de auditoria ao lado do ledger.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validação do double-entry:&lt;/strong&gt; toda transaction precisa de pelo menos uma entry de débito e uma de crédito, e &lt;strong&gt;débitos = créditos em cada moeda&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Por que balancear por moeda:&lt;/strong&gt; numa compra de 1 ETH com dólares, validar só o total quebra — dá para creditar ETH criado do nada e debitar dólares que simplesmente somem. O certo é &lt;strong&gt;agrupar as entries por moeda&lt;/strong&gt; e validar cada grupo. Uma conversão de moeda sempre envolve pelo menos 4 contas (a plataforma precisa de uma conta em ETH de onde sai a cripto e de uma em dólar onde entra o dinheiro do cliente); modelar com só 2 contas e uma taxa de câmbio não funciona, porque a taxa varia no tempo e não existe uma taxa única aceita por todos.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:21&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;EntryRepository.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Busca as entries presentes numa conta num determinado effective time&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Entry&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; findEntriesAt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; throws SQLException &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sql &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;SELECT * FROM entries &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;WHERE account_id = ? &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;  AND effective_at &amp;#x3C;= ? &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;  AND (discarded_at IS NULL OR discarded_at &gt;= ?)&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Connection&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conn &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; dataSource&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getConnection&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;PreparedStatement&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; stmt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; conn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;prepareStatement&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setTimestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Timestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;setTimestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Timestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;timestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ResultSet&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; rs &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; stmt&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;executeQuery&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Entry&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entries &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;ArrayList&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&amp;#x3C;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;rs&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;entries&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Entry&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;fromResultSet&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;rs&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entries&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-v&quot;&gt;How to Scale a Ledger, Part V&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;7-part-vi--concorrência-performance-e-o-job-de-conciliação&quot;&gt;7. Part VI — concorrência, performance e o job de conciliação&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; as duas últimas garantias — controle de concorrência (evitar gastar o mesmo dinheiro duas vezes) e performance (leitura rápida de saldo) — e o &lt;strong&gt;job que detecta drift no cache de saldo&lt;/strong&gt;, que fecha o padrão “registro + saldo + conciliação”. É o artigo que melhor mostra a conciliação interna na prática.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chaves de idempotência:&lt;/strong&gt; o cenário clássico — o cliente envia o pedido, o ledger demora, o cliente estoura o timeout e tenta de novo; o pedido original termina e o ledger cria a transaction duas vezes. A solução é deduplicar com uma chave de idempotência: uma string enviada pelo cliente e &lt;strong&gt;gerada fora do loop de retry&lt;/strong&gt;, para que todas as tentativas usem a mesma. Se o ledger recebe uma chave que já conhece, devolve a resposta da primeira requisição. As chaves ficam guardadas por 24 horas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance — cache de saldo:&lt;/strong&gt; calcular o saldo somando as entries é O(n) e fica lento com dezenas ou centenas de milhares de entries. A solução é &lt;strong&gt;cachear&lt;/strong&gt; &lt;code&gt;pending_debits&lt;/code&gt;, &lt;code&gt;pending_credits&lt;/code&gt;, &lt;code&gt;posted_debits&lt;/code&gt; e &lt;code&gt;posted_credits&lt;/code&gt; numa linha da conta.
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cache do saldo atual:&lt;/strong&gt; reflete todas as entries e é atualizado &lt;strong&gt;de forma síncrona&lt;/strong&gt; quando entries de autorização são gravadas, porque é ele que sustenta o balance locking. Quem faz a conta de forma atômica é o banco.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cache de saldo por data efetiva:&lt;/strong&gt; mais complexo, com duas abordagens — &lt;em&gt;anchoring&lt;/em&gt; (guarda o saldo do fim de cada dia e aplica as entries do dia por cima) e &lt;em&gt;resulting balances&lt;/em&gt; (guarda o saldo resultante após cada entry, útil para contas com muitas entries no mesmo dia). No anchoring, a atualização é assíncrona: as entries entram numa fila e o cache é atualizado em lotes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitorando o drift do cache (o job de conciliação):&lt;/strong&gt; ler o saldo do cache melhora a performance, mas o cache pode divergir das entries, que são a fonte da verdade. O tratamento tem três passos:
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Verificar regularmente&lt;/strong&gt; se o saldo em cache de cada conta bate com a &lt;strong&gt;soma das entries&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Desligar automaticamente&lt;/strong&gt; a leitura do cache nas contas com drift.&lt;/li&gt;
&lt;li&gt;Oferecer &lt;strong&gt;ferramentas de backfill&lt;/strong&gt; (recalcular o cache a partir das entries) e um runbook para o plantão investigar e corrigir o drift.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/job-de-conciliacao.svg&quot; alt=&quot;O job de conciliação compara a soma das entries com o saldo em cache e, se houver drift, desliga a leitura do cache e aciona backfill e runbook&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tópicos avançados de escala:&lt;/strong&gt; &lt;em&gt;account categories&lt;/em&gt; (um modelo em grafo para agregar grupos de contas em relatórios); busca de transactions com paginação por cursor, não por offset; &lt;strong&gt;filas de escrita assíncronas&lt;/strong&gt; que absorvem picos de carga — as fintechs líderes passam facilmente de 5.000 QPS (requisições por segundo); e sharding de contas entre bancos, seja manual, seja com bancos distribuídos como Spanner ou CockroachDB — com o desafio de manter a atomicidade do double-entry entre shards.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:10&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;RetryComIdempotencia.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Idempotency key gerada FORA do loop de retry (mesma string em todas as tentativas)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; idempotencyKey &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; UUID&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;randomUUID&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;TransactionResponse&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; response &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; attempt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; attempt &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; MAX_ATTEMPTS&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; attempt&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;response &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; createTransaction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;idempotencyKey&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;response&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;isSuccessful&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;())&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;break&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:11&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ReconciliationJob.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Conceito do job de conciliação: comparar saldo em cache com a soma das entries&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; reconcileAccount&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; throws SQLException &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cachedBalance &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; balanceCache&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;getBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; computedBalance &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; sumAllEntries&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// SUM() sobre as entries&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;cachedBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;compareTo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;computedBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Drift detectado: desliga a leitura do cache e alerta o plantão (backfill + runbook)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;balanceCache&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;disableReads&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;alerting&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;raiseDrift&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; cachedBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; computedBalance&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-vi&quot;&gt;How to Scale a Ledger, Part VI&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;8-accounting-for-developers-part-i--os-fundamentos&quot;&gt;8. Accounting for Developers, Part I — os fundamentos&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; introdução à contabilidade para desenvolvedores: os conceitos de double-entry traduzidos para termos técnicos, para quem constrói sistemas que movem dinheiro.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Princípio central:&lt;/strong&gt; toda transaction registra &lt;strong&gt;de onde o dinheiro veio&lt;/strong&gt; e &lt;strong&gt;em que foi usado&lt;/strong&gt;. Com isso você reconstrói saldos em qualquer data, rastreia o movimento com auditabilidade total e alinha a lógica do sistema com as finanças reais.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Falha mais comum:&lt;/strong&gt; o software criar ou destruir registros de dinheiro por acidente. Os sintomas: registros internos diferentes do extrato do banco, ferramentas de conciliação apontando divergências, saldos que não fazem sentido diante das transactions. Uber, Square e Airbnb são citadas como empresas que adotaram double-entry.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conceitos:&lt;/strong&gt; &lt;strong&gt;account&lt;/strong&gt; (porção separada de valor), &lt;strong&gt;transaction&lt;/strong&gt; (evento atômico que afeta saldos; tem pelo menos duas entries, afeta duas ou mais contas e mantém o ledger balanceado) e &lt;strong&gt;ledger&lt;/strong&gt; (log de eventos com impacto monetário).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Não altere saldos diretamente:&lt;/strong&gt; guarde transactions imutáveis e &lt;strong&gt;sempre calcule o saldo a partir delas&lt;/strong&gt;. Alterar o saldo direto parece mais simples e eficiente, mas gera um sistema propenso a erros difíceis de detectar e de conciliar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Debit normal × credit normal:&lt;/strong&gt; contas debit normal representam o que você tem ou os usos do dinheiro (ativos, despesas) e aumentam com débito; contas credit normal representam o que você deve ou as fontes do dinheiro (passivos, patrimônio líquido, receita) e aumentam com crédito.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Tipo de conta, Débito, Crédito&quot;&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tipo de conta&lt;/th&gt;&lt;th&gt;Débito&lt;/th&gt;&lt;th&gt;Crédito&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Ativo (asset)&lt;/td&gt;&lt;td&gt;+&lt;/td&gt;&lt;td&gt;−&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Passivo (liability)&lt;/td&gt;&lt;td&gt;−&lt;/td&gt;&lt;td&gt;+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Patrimônio líquido (equity)&lt;/td&gt;&lt;td&gt;−&lt;/td&gt;&lt;td&gt;+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Receita (revenue)&lt;/td&gt;&lt;td&gt;−&lt;/td&gt;&lt;td&gt;+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Despesa (expense)&lt;/td&gt;&lt;td&gt;+&lt;/td&gt;&lt;td&gt;−&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ledger balanceado:&lt;/strong&gt; a soma dos saldos das contas credit normal é igual à soma dos saldos das contas debit normal. Se não bate, o sistema criou ou perdeu dinheiro do nada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detalhe contraintuitivo:&lt;/strong&gt; duas contas podem aumentar &lt;strong&gt;ao mesmo tempo&lt;/strong&gt;. No exemplo do artigo, a Modern Bagelry, uma loja on-line de bagels, recebe um aporte de $1 milhão: o caixa (ativo, debit normal) sobe com um débito e o patrimônio líquido (credit normal) sobe com um crédito.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/accounting-for-developers-part-i&quot;&gt;Accounting for Developers, Part I&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;9-part-ii--o-ledger-de-uma-carteira-digital&quot;&gt;9. Part II — o ledger de uma carteira digital&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; aplica os fundamentos construindo, passo a passo, o ledger de uma carteira digital no estilo do Venmo: requisitos → plano de contas → modelagem das transactions → modelagem do banco.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plano de contas (chart of accounts) do app:&lt;/strong&gt; &lt;strong&gt;Cash&lt;/strong&gt; (o dinheiro real no banco) → ativo, debit normal; &lt;strong&gt;saldo da carteira de cada usuário&lt;/strong&gt; (uma conta por usuário) → passivo, credit normal (a empresa “deve” esse dinheiro ao usuário); &lt;strong&gt;taxas de processamento de cartão&lt;/strong&gt; → despesa, debit normal; &lt;strong&gt;receita&lt;/strong&gt; com tarifas → credit normal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Três transactions modeladas:&lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Transferência ($100 de A para B):&lt;/strong&gt; debita a carteira de quem envia e credita a de quem recebe.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Depósito com cartão:&lt;/strong&gt; crédito de $300 na carteira, contrabalançado por dois débitos — taxa de cartão ($6, ou 2%) e caixa ($294). Um único evento com várias entries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saque:&lt;/strong&gt; saque de $500 com tarifa de 0,5% ($2,50) → debita $502,50 da carteira, credita $497,50 no caixa e $2,50 na receita.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modelagem do banco:&lt;/strong&gt; &lt;code&gt;accounts&lt;/code&gt; (&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;user_id&lt;/code&gt;, &lt;code&gt;account_type&lt;/code&gt;, &lt;code&gt;normality&lt;/code&gt;), &lt;code&gt;transactions&lt;/code&gt; (&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;timestamp&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;) e &lt;code&gt;entries&lt;/code&gt; (&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;transaction_id&lt;/code&gt;, &lt;code&gt;account_id&lt;/code&gt;, &lt;code&gt;amount&lt;/code&gt;, &lt;code&gt;direction&lt;/code&gt;). &lt;strong&gt;Invariante a garantir:&lt;/strong&gt; soma dos débitos = soma dos créditos &lt;strong&gt;em cada transaction&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:22&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;ModeloLedger.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Normality&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;DEBIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;CREDIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Direction&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;DEBIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;CREDIT&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// userId é nulo nas contas internas; accountType: &quot;USER_WALLET&quot;, &quot;CASH&quot;, &quot;REVENUE&quot;, &quot;CARD_FEES&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Account&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; userId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Normality&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; normality&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;Entry&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; transactionId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; accountId&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; amount&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Direction&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;record&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#3F5878;--1:#9DB3D4&quot;&gt;LedgerTransaction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;long&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Instant&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; timestamp&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; description&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;List&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Entry&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entries&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Invariante: soma dos débitos == soma dos créditos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;boolean&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; isBalanced&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; total&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DEBIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;compareTo&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;total&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CREDIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; total&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;Direction&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; entries&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;stream&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;e &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; e&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Entry&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;amount&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;reduce&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;ZERO&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;O depósito do artigo, montado com esse modelo:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:7&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Deposito.java&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// Contas: 1 = carteira do Art, 2 = taxas de cartão, 3 = caixa&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; deposito &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; LedgerTransaction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Instant&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;now&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;Depósito com cartão&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Entry&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;300.00&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;CREDIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Entry&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;101&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;6.00&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DEBIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Entry&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;102&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; BigDecimal&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;294.00&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;),&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; Direction&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;DEBIT&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;println&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;deposito&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;isBalanced&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;());&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Com várias moedas, a mesma checagem deve ser feita em cada moeda, como mostra a Part V.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/accounting-for-developers-part-ii&quot;&gt;Accounting for Developers, Part II&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;10-part-iii--um-marketplace-de-empréstimos&quot;&gt;10. Part III — um marketplace de empréstimos&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; aplica os princípios num marketplace de empréstimos entre pessoas (P2P), com juros, amortização, investidores e tomadores.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dois tipos de dado:&lt;/strong&gt; o &lt;strong&gt;histórico&lt;/strong&gt; (o que já aconteceu, baseado em transactions lançadas) fica no ledger; o &lt;strong&gt;prospectivo&lt;/strong&gt; (taxas de juros, prazos, divisão de cada parcela entre juros e principal) fica &lt;strong&gt;fora&lt;/strong&gt; dele, numa &lt;strong&gt;tabela de amortização&lt;/strong&gt;. Separar os dois mantém o ledger limpo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plano de contas:&lt;/strong&gt; caixa (debit normal), receita de juros (credit normal) e &lt;strong&gt;duas contas por usuário&lt;/strong&gt; (principal e juros). As contas do investidor são credit normal (a plataforma deve a ele); as do tomador são debit normal (ele deve à plataforma).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cinco transactions modeladas:&lt;/strong&gt; depósito do investidor; desembolso ao tomador; &lt;strong&gt;apropriação mensal de juros&lt;/strong&gt;; pagamento mensal do tomador; pagamento ao investidor no vencimento. Na apropriação de juros, o investidor recebe 4,8% ao ano e o tomador paga 12%: credita $40 por mês nos juros do investidor, debita $50 nos juros do tomador, e a diferença de $10 vai para a &lt;strong&gt;receita&lt;/strong&gt; — o spread da plataforma.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arquitetura final:&lt;/strong&gt; um &lt;strong&gt;ledger central&lt;/strong&gt; com as restrições de double-entry, um &lt;strong&gt;Transaction Logic Service&lt;/strong&gt; (converte eventos e webhooks em entries válidas), uma &lt;strong&gt;tabela de amortização&lt;/strong&gt; (calcula as parcelas) e um &lt;strong&gt;plano de contas&lt;/strong&gt; com pelo menos 6 tipos de conta.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.moderntreasury.com/journal/accounting-for-developers-part-iii&quot;&gt;Accounting for Developers, Part III&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;11-arquitetura-de-plataformas-de-fidelidade-open-loyalty&quot;&gt;11. Arquitetura de plataformas de fidelidade (Open Loyalty)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; a arquitetura de plataformas de pontos e fidelidade — um domínio onde o mesmo padrão de ledger aparece fora do dinheiro. O artigo defende plataformas modulares e API-first, com o &lt;strong&gt;ledger de pontos&lt;/strong&gt; como um dos componentes centrais.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pontos importantes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Componentes centrais:&lt;/strong&gt; motor de regras (avalia as ações do cliente e decide o que disparar), &lt;strong&gt;ledger de pontos&lt;/strong&gt; (cada ponto ganho, resgatado, transferido ou expirado, com trilha de auditoria completa), serviço de entrega das recompensas (&lt;em&gt;fulfillment&lt;/em&gt;), camada de API, camada de eventos e mensageria e camada de dados do cliente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O ledger de pontos é um dos componentes mais exigentes:&lt;/strong&gt; quando o cliente conclui uma compra, &lt;strong&gt;os pontos devem ser creditados exatamente uma vez&lt;/strong&gt;, mesmo que a requisição seja repetida ou processada duas vezes. Um ledger que erra isso produz erros de saldo difíceis de detectar e caros de corrigir. Plataformas modernas o tratam como &lt;strong&gt;serviço independente&lt;/strong&gt;, e não como um campo no cadastro do cliente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idempotência na API é essencial&lt;/strong&gt; — concessão ou resgate duplicado de pontos é um risco operacional real.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fluxo ponta a ponta:&lt;/strong&gt; compra → chamada de API → a camada de eventos roteia para o motor de regras → o motor avalia campanhas e categoria do cliente → o fulfillment gera a recompensa → &lt;strong&gt;o ledger é atualizado com registro de auditoria&lt;/strong&gt; → o evento “recompensa emitida” segue para os outros sistemas. As falhas ficam contidas: se o fulfillment atrasa, a atualização do ledger ainda termina.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quando essa complexidade não é necessária:&lt;/strong&gt; num programa simples, no início ou em um único canal, uma plataforma tudo-em-um é mais pragmática. A arquitetura deve seguir as necessidades reais do programa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://www.openloyalty.io/insider/loyalty-system-architecture-how-modern-platforms-are-built&quot;&gt;Loyalty System Architecture&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;12-payment-ledger-architecture-trio--os-6-fatores&quot;&gt;12. Payment Ledger Architecture (Trio) — os 6 fatores&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Visão geral:&lt;/strong&gt; define um ledger de pagamentos por seis fatores e apresenta a stack em que a maioria dos sistemas em produção converge. É o resumo mais direto e prático do conjunto.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Os 6 fatores:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Double-entry como invariante do banco, não da aplicação:&lt;/strong&gt; débito, crédito e metadados da mesma entry são gravados numa &lt;strong&gt;única transação atômica de banco&lt;/strong&gt;. Uma CHECK constraint ou uma validação antes do commit confirma que a entry soma zero. Errar isso gera drift de saldo silencioso.
Um cuidado prático: no PostgreSQL, uma CHECK constraint só enxerga a linha que está sendo gravada. Se débito e crédito ficam em linhas separadas, a soma precisa ser validada por um &lt;em&gt;constraint trigger&lt;/em&gt; adiado para o fim da transação (&lt;code&gt;DEFERRABLE INITIALLY DEFERRED&lt;/code&gt;) ou pela aplicação antes do commit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Derivar saldos das entries, nunca guardar um saldo corrente:&lt;/strong&gt; uma coluna &lt;code&gt;balance&lt;/code&gt; mutável &lt;strong&gt;sofre drift&lt;/strong&gt; com escrita concorrente, falha parcial, correção manual ou migração. Em escala, fazer &lt;code&gt;SUM()&lt;/code&gt; a cada leitura fica caro, então crie um &lt;strong&gt;saldo materializado&lt;/strong&gt;: uma visão em cache, otimizada para leitura, recalculada quando novas entries são lançadas — e &lt;strong&gt;sempre conferida contra as entries na conciliação&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Journals imutáveis com reversões explícitas (sem UPDATE nem DELETE):&lt;/strong&gt; o &lt;em&gt;journal&lt;/em&gt; é a tabela de lançamentos, e ela precisa ser inalterável para valer em auditorias (SOC 2, PCI DSS, exames de AML/KYC). Reverter = lançar uma &lt;strong&gt;nova&lt;/strong&gt; entry compensatória. O usuário de banco usado pelo posting engine (o serviço que grava os lançamentos) &lt;strong&gt;não deve ter permissão&lt;/strong&gt; de UPDATE ou DELETE nas tabelas de journal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modelo de três saldos:&lt;/strong&gt; &lt;strong&gt;ledger balance&lt;/strong&gt; (liquidado), &lt;strong&gt;pending&lt;/strong&gt; (em trânsito) e &lt;strong&gt;available&lt;/strong&gt; (o que pode ser gasto agora). Juntar os três num só aumenta o risco de o cliente gastar mais do que tem, inclusive valores bloqueados ou ainda em trânsito.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CQRS — separar escrita e leitura:&lt;/strong&gt; a escrita é fortemente consistente, atômica e durável; a leitura é rápida, via saldo materializado. Quando o saldo alimenta uma &lt;strong&gt;decisão financeira&lt;/strong&gt;, o posting engine valida contra o journal, não contra a visão materializada, que pode estar defasada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conciliação como entregável de engenharia, não planilha do financeiro:&lt;/strong&gt; há a correção &lt;strong&gt;interna&lt;/strong&gt; (entries balanceadas, saldos derivados batendo com o journal) e a &lt;strong&gt;externa&lt;/strong&gt; (o ledger batendo com processadora, bandeira, banco parceiro e câmara de compensação). O caminho é um &lt;strong&gt;pipeline automatizado&lt;/strong&gt; que roda todo dia ou após cada janela de liquidação, compara linha a linha e expõe as divergências com classificação de severidade (diferença de prazo × divergência real), alertas e acompanhamento das exceções. Segundo o artigo, o colapso da Synapse em 2024 foi em grande parte uma falha de conciliação do ledger.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;A stack de referência:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/arquitetura-de-ledger/stack-de-referencia.svg&quot; alt=&quot;Stack de referência: posting engine grava no journal do PostgreSQL e publica no Kafka; o balance materializer mantém os saldos, com Redis para contas quentes; o pipeline de conciliação compara arquivos externos com o journal e registra exceções&quot;&gt;&lt;/p&gt;
&lt;p&gt;No diagrama, o &lt;strong&gt;posting engine&lt;/strong&gt; valida o double-entry, grava as entries atomicamente no &lt;strong&gt;journal&lt;/strong&gt; (PostgreSQL, append-only) e publica o evento &lt;code&gt;JournalEntryPosted&lt;/code&gt; no &lt;strong&gt;Kafka&lt;/strong&gt;. O &lt;strong&gt;balance materializer&lt;/strong&gt; consome esses eventos e mantém os três saldos, usando &lt;strong&gt;Redis&lt;/strong&gt; para contas muito movimentadas. O &lt;strong&gt;pipeline de conciliação&lt;/strong&gt; roda em jobs agendados (Airflow, Dagster ou Prefect): lê os arquivos externos — relatórios da processadora, extratos bancários, arquivos da bandeira —, compara cada linha com o journal e grava as divergências numa tabela de exceções, com alertas. Para volumes muito altos, o artigo cita bancos SQL distribuídos como CockroachDB e Google Spanner.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Construir ou comprar:&lt;/strong&gt; construa se o ledger é diferencial competitivo, se o time já construiu ledgers em produção ou se os requisitos vão além do que um Ledger-as-a-Service (LaaS, ledger oferecido como serviço) suporta. Use LaaS ou open-source (Formance Ledger, Blnk) se o ledger é infraestrutura e o tempo até o mercado importa mais. A maioria começa melhor com LaaS ou open-source e migra para uma solução própria quando a plataforma deixa de atender algum requisito.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fonte:&lt;/strong&gt; &lt;a href=&quot;https://trio.dev/payment-ledger-architecture-fintech/&quot;&gt;Payment Ledger Architecture: How Modern Fintechs Design Ledgers&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;síntese--o-padrão-em-que-os-12-artigos-convergem&quot;&gt;Síntese — o padrão em que os 12 artigos convergem&lt;/h2&gt;
&lt;p&gt;Independentemente do domínio — banco digital, carteira, marketplace, programa de pontos —, o desenho final é o mesmo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cada movimento&lt;/strong&gt; é uma entry imutável num ledger append-only, protegida por &lt;strong&gt;chave de idempotência&lt;/strong&gt; para nunca ser lançada duas vezes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O saldo&lt;/strong&gt; é um &lt;strong&gt;saldo materializado&lt;/strong&gt;: um cache de leitura rápida, atualizado de forma síncrona quando sustenta autorizações (seção 7) ou de forma assíncrona a partir dos eventos (seção 12) — mas sempre &lt;strong&gt;derivado e reconstruível&lt;/strong&gt; a partir das entries, nunca a fonte da verdade.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A conciliação&lt;/strong&gt; é um job ou pipeline que soma as entries de cada conta, compara com o saldo materializado, detecta drift, desliga a leitura do cache da conta afetada e alerta — e, havendo sistema externo, confere o ledger também contra ele.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double-entry vale além do dinheiro.&lt;/strong&gt; Levando o raciocínio dos artigos para um programa de pontos: ao conceder pontos, credita-se a conta do cliente e debita-se uma conta interna de pontos emitidos. Assim a soma sempre fecha e qualquer drift fica detectável.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Quando um efeito externo (a captura no parceiro, por exemplo) pode dar certo sem que o registro local seja gravado, a conciliação externa ganha um aliado: gravar a intenção antes de agir, tema de &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/efeito-externo-sem-registro-local/&quot;&gt;Efeito externo sem registro local&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;p&gt;Os 12 artigos resumidos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://new2026.medium.com/building-a-reliable-ledger-in-an-event-sourced-system-without-big-db-transactions-879061a7ff87&quot;&gt;Building a Reliable Ledger in an Event-Sourced System Without Big DB Transactions&lt;/a&gt; — Medium&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-i&quot;&gt;How to Scale a Ledger, Part I&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-ii&quot;&gt;How to Scale a Ledger, Part II&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-iii&quot;&gt;How to Scale a Ledger, Part III&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-iv&quot;&gt;How to Scale a Ledger, Part IV&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-v&quot;&gt;How to Scale a Ledger, Part V&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-vi&quot;&gt;How to Scale a Ledger, Part VI&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/accounting-for-developers-part-i&quot;&gt;Accounting for Developers, Part I&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/accounting-for-developers-part-ii&quot;&gt;Accounting for Developers, Part II&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moderntreasury.com/journal/accounting-for-developers-part-iii&quot;&gt;Accounting for Developers, Part III&lt;/a&gt; — Modern Treasury&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.openloyalty.io/insider/loyalty-system-architecture-how-modern-platforms-are-built&quot;&gt;Loyalty system architecture: How modern platforms are built&lt;/a&gt; — Open Loyalty&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://trio.dev/payment-ledger-architecture-fintech/&quot;&gt;Payment Ledger Architecture: How Modern Fintechs Design Ledgers&lt;/a&gt; — Trio&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Documentação usada nos exemplos e observações técnicas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/ddl-constraints.html&quot;&gt;PostgreSQL — Constraints&lt;/a&gt; (CHECK constraint só valida a linha gravada)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/sql-createtrigger.html&quot;&gt;PostgreSQL — CREATE TRIGGER&lt;/a&gt; (constraint triggers adiados)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/errcodes-appendix.html&quot;&gt;PostgreSQL — Error Codes&lt;/a&gt; (&lt;code&gt;23505 unique_violation&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Arquitetura de Software</category><category>Pagamentos</category><category>Banco de Dados</category><category>Idempotência</category></item><item><title>SNS MessageAttributes e Filter Policy — filtrando mensagens antes do SQS</title><link>https://blog.cesarschutz.com.br/posts/sns-filter-policy/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/sns-filter-policy/</guid><description>Como fazer o SNS entregar a cada fila SQS só as mensagens que interessam: atributos de mensagem, filter policy na assinatura, filtro por atributo ou pelo corpo, operadores, limites e cuidados.</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Quando um tópico SNS tem várias filas SQS assinando (o chamado &lt;em&gt;fan-out&lt;/em&gt;), &lt;strong&gt;cada fila recebe, por padrão, todas as mensagens publicadas no tópico&lt;/strong&gt;. Se o consumidor só se interessa por um tipo de evento, ele precisa receber, ler e descartar o resto, pagando por isso. A &lt;strong&gt;filter policy&lt;/strong&gt; resolve esse problema: é uma regra em JSON configurada na &lt;strong&gt;assinatura&lt;/strong&gt; que faz o próprio SNS decidir quais mensagens entrega àquela fila. O que não passa no filtro não é enviado à fila.&lt;/p&gt;
&lt;p&gt;Neste post: como marcar a mensagem com &lt;strong&gt;MessageAttributes&lt;/strong&gt; no produtor, como escrever e aplicar a filter policy, como o SNS avalia a regra, a diferença entre filtrar por atributo e pelo corpo da mensagem, e os limites e cuidados.&lt;/p&gt;
&lt;h2 id=&quot;os-termos-em-uma-frase&quot;&gt;Os termos em uma frase&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tópico&lt;/strong&gt;: o canal onde o produtor publica. &lt;strong&gt;Assinatura&lt;/strong&gt; (&lt;em&gt;subscription&lt;/em&gt;): o vínculo entre o tópico e um destino, como uma fila SQS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MessageAttributes&lt;/strong&gt;: metadados opcionais enviados &lt;strong&gt;junto com a mensagem, mas fora do corpo&lt;/strong&gt;. Cada atributo tem nome, tipo (&lt;code&gt;String&lt;/code&gt;, &lt;code&gt;String.&lt;wbr&gt;Array&lt;/code&gt;, &lt;code&gt;Number&lt;/code&gt; ou &lt;code&gt;Binary&lt;/code&gt;) e valor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Filter policy&lt;/strong&gt;: JSON guardado na assinatura que diz quais mensagens ela aceita. Assinatura sem filter policy recebe tudo.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;como-funciona-na-prática&quot;&gt;Como funciona na prática&lt;/h2&gt;
&lt;p&gt;Ao publicar, o produtor adiciona um atributo que identifica o tipo de evento. Com Spring Cloud AWS, os headers da mensagem viram MessageAttributes do SNS (um header &lt;code&gt;String&lt;/code&gt; vira atributo do tipo &lt;code&gt;String&lt;/code&gt;), e o &lt;code&gt;convertAndSend&lt;/code&gt; do &lt;code&gt;SnsTemplate&lt;/code&gt; criado pela autoconfiguração serializa o evento em JSON no corpo:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Produtor (Spring Cloud AWS)&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;Java&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;java&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;snsTemplate&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;convertAndSend&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;topicArn&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;                                    &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// corpo: o evento serializado em JSON&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;eventType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;OrderCreatedEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#5E6361;--0fs:italic;--1:#989F9C;--1fs:italic&quot;&gt;// header que vira MessageAttribute no SNS&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Cuidado com a variante &lt;code&gt;send(topicArn, message)&lt;/code&gt;: ela não converte o payload e publica o &lt;code&gt;toString()&lt;/code&gt; do objeto, então só use com payload já em &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Sem Spring, o equivalente é preencher &lt;code&gt;MessageAttributes&lt;/code&gt; na chamada &lt;code&gt;Publish&lt;/code&gt; da API do SNS, com &lt;code&gt;DataType&lt;/code&gt; &lt;code&gt;String&lt;/code&gt; e &lt;code&gt;StringValue&lt;/code&gt; &lt;code&gt;OrderCreatedEvent&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Na assinatura da fila, você configura a filter policy:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:1&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Filter policy da assinatura&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;eventType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;OrderCreatedEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Ela é gravada no atributo &lt;code&gt;FilterPolicy&lt;/code&gt; da assinatura, pelo console, pela CLI, pelos SDKs ou por CloudFormation:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal has-title&quot; style=&quot;--linhas:4&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Aplicando pela AWS CLI&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt;aws &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;sns&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;set-subscription-attributes&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--subscription-arn&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;arn:aws:sns:...&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--attribute-name&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;FilterPolicy&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;--attribute-value&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;{&quot;eventType&quot;: [&quot;OrderCreatedEvent&quot;]}&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Resultado: essa fila só recebe mensagens com &lt;code&gt;eventType = OrderCreatedEvent&lt;/code&gt;. Os outros tipos publicados no mesmo tópico não são entregues a ela. O filtro vale &lt;strong&gt;por assinatura&lt;/strong&gt;: no diagrama abaixo, cada fila tem o seu, e uma mensagem que não casa com nenhum deles não chega a fila nenhuma.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/sns-filter-policy/filter-policy-fanout.svg&quot; alt=&quot;Produtor publica três tipos de evento; o SNS entrega OrderCreatedEvent só à fila A, OrderCancelledEvent só à fila B, e OrderShippedEvent a nenhuma&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;como-o-sns-avalia-a-regra&quot;&gt;Como o SNS avalia a regra&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chaves diferentes = E (AND)&lt;/strong&gt;: a mensagem precisa satisfazer todas as chaves da policy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Valores no mesmo array = OU (OR)&lt;/strong&gt;: basta casar com um deles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Atributo ausente reprova&lt;/strong&gt;: se a policy exige &lt;code&gt;eventType&lt;/code&gt; e a mensagem não tem esse atributo, ela não é entregue (a exceção é &lt;code&gt;&quot;exists&quot;: false&lt;/code&gt;, que casa justamente com a ausência). Atributos da mensagem que a policy não cita são ignorados.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comparação de strings diferencia maiúsculas de minúsculas&lt;/strong&gt;, a menos que você use &lt;code&gt;equals-ignore-case&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Além da igualdade exata, a policy aceita operadores. Os mais úteis:&lt;/p&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Tabela: Operador, Exemplo, Casa quando&quot;&gt;












































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Operador&lt;/th&gt;&lt;th&gt;Exemplo&lt;/th&gt;&lt;th&gt;Casa quando&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;anything-but&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[{&quot;anything-but&quot;: [&quot;OrderShippedEvent&quot;]}]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;o valor &lt;strong&gt;não&lt;/strong&gt; é nenhum dos listados&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;prefix&lt;/code&gt; / &lt;code&gt;suffix&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[{&quot;prefix&quot;: &quot;Order&quot;}]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;o valor começa (ou termina) com o texto&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;equals-ignore-case&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[{&quot;equals-ignore-case&quot;: &quot;ordercreatedevent&quot;}]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;igualdade sem diferenciar maiúsculas de minúsculas&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;numeric&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[{&quot;numeric&quot;: [&quot;&gt;=&quot;, 100, &quot;&amp;#x3C;&quot;, 500]}]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;o número está na faixa&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;exists&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[{&quot;exists&quot;: true}]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;o atributo está presente (ou ausente, com &lt;code&gt;false&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cidr&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[{&quot;cidr&quot;: &quot;10.0.0.0/24&quot;}]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;o IP pertence à sub-rede&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;$or&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;{&quot;$or&quot;: [{...}, {...}]}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;uma das condições (entre chaves diferentes) é verdadeira&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Um exemplo combinando AND, OR e operadores: aceita pedidos criados &lt;strong&gt;ou&lt;/strong&gt; cancelados, de lojas cujo código começa com &lt;code&gt;loja-&lt;/code&gt;, com valor a partir de 100 (publique &lt;code&gt;total&lt;/code&gt; como atributo do tipo &lt;code&gt;Number&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:5&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Filter policy com operadores&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;eventType&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;OrderCreatedEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;OrderCancelledEvent&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;store&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;prefix&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;loja-&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;total&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;filtrar-por-atributo-ou-pelo-corpo&quot;&gt;Filtrar por atributo ou pelo corpo&lt;/h2&gt;
&lt;p&gt;O atributo &lt;code&gt;FilterPolicyScope&lt;/code&gt; da assinatura define onde o SNS procura os campos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MessageAttributes&lt;/code&gt;&lt;/strong&gt; (padrão): a policy é comparada com os atributos da mensagem. Não aceita policy aninhada, compara só atributos &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;String.&lt;wbr&gt;Array&lt;/code&gt; e &lt;code&gt;Number&lt;/code&gt;, e &lt;strong&gt;ignora atributos &lt;code&gt;Binary&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MessageBody&lt;/code&gt;&lt;/strong&gt;: a policy é comparada com os campos do corpo, que precisa ser um objeto JSON válido. Aceita policy aninhada, espelhando a estrutura do JSON.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Por exemplo, para um corpo &lt;code&gt;{&quot;order&quot;: {&quot;status&quot;: &quot;CREATED&quot;, &quot;total&quot;: 250}}&lt;/code&gt;, esta policy aninhada aceita a mensagem:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot; style=&quot;--linhas:6&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;Filter policy com escopo MessageBody&lt;/span&gt; &lt;span class=&quot;linguagem&quot;&gt;JSON&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;CREATED&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;total&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[{&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2549B8;--1:#93AEFF&quot;&gt;numeric&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#654262;--1:#C7A3C2&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#1A2124;--1:#E7E9E4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#57605E;--1:#A9B0AC&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Filtrar pelo corpo é útil quando você não controla o produtor e ele não publica atributos. Mesmo assim, o filtro por atributo continua sendo o caminho padrão por dois motivos: &lt;strong&gt;é gratuito&lt;/strong&gt;, enquanto o filtro pelo corpo é cobrado por GB de payload analisado (contando tanto as mensagens entregues quanto as filtradas), e não acopla a regra ao formato do payload.&lt;/p&gt;
&lt;h2 id=&quot;por-que-isso-importa&quot;&gt;Por que isso importa&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sem filter policy&lt;/strong&gt;: todas as mensagens do tópico chegam à fila, e o consumidor recebe e descarta o que não é dele.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Com filter policy&lt;/strong&gt;: só o que interessa chega. São menos requisições ao SQS (que cobra por requisição: envio, recebimento e exclusão contam), menos transferência de dados do SNS para o SQS (cobrada por volume entregue) e menos processamento desperdiçado no consumidor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O filtro fica na assinatura, não no produtor&lt;/strong&gt;: o produtor não precisa saber quem consome. É o desacoplamento clássico do &lt;em&gt;pub/sub&lt;/em&gt; (publicação e assinatura), só que com entrega seletiva.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MessageAttributes também servem para outras coisas além de filtro, como propagar o ID de rastreamento entre serviços; veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/w3c-trace-context/&quot;&gt;W3C Trace Context&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;limites-e-cuidados&quot;&gt;Limites e cuidados&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tamanho da policy&lt;/strong&gt;: no máximo &lt;strong&gt;5 chaves&lt;/strong&gt; e &lt;strong&gt;150 combinações&lt;/strong&gt;. As combinações são o produto da quantidade de valores de cada chave: chaves com 3, 1 e 2 valores dão 3 × 1 × 2 = 6. A policy pode ter até 256 KB.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quantidade de policies&lt;/strong&gt;: por padrão, até &lt;strong&gt;200 por tópico&lt;/strong&gt; e &lt;strong&gt;10.000 por conta&lt;/strong&gt;, ajustáveis pelo Service Quotas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mudança não é instantânea&lt;/strong&gt;: criar ou alterar uma filter policy leva &lt;strong&gt;até 15 minutos&lt;/strong&gt; para valer por completo (consistência eventual). Não conclua que o filtro falhou logo após o deploy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raw message delivery&lt;/strong&gt;: com &lt;em&gt;raw message delivery&lt;/em&gt; ligado (a fila recebe a mensagem sem o envelope JSON do SNS), a assinatura SQS aceita &lt;strong&gt;no máximo 10 atributos&lt;/strong&gt;; mensagens com mais que isso são descartadas. Atenção com frameworks: o Spring Cloud AWS também envia como atributos os headers &lt;code&gt;id&lt;/code&gt; e &lt;code&gt;timestamp&lt;/code&gt; que toda &lt;code&gt;Message&lt;/code&gt; do Spring recebe automaticamente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Um filtro errado descarta mensagens em silêncio&lt;/strong&gt;: um nome de atributo digitado errado faz a mensagem simplesmente não ser entregue. Monitore a métrica &lt;code&gt;NumberOfNotificationsFilteredOut&lt;/code&gt; do CloudWatch (e as variantes &lt;code&gt;-NoMessageAttributes&lt;/code&gt; e &lt;code&gt;-InvalidAttributes&lt;/code&gt;) para perceber quando o filtro barra mais do que deveria.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.cesarschutz.com.br/posts/sns-filter-policy/#apresentacao&quot;&gt;Apresentação em slides, no site&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/sns-message-filtering.html&quot;&gt;Amazon SNS message filtering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html&quot;&gt;Amazon SNS subscription filter policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/subscription-filter-policy-constraints.html&quot;&gt;Filter policy constraints in Amazon SNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/and-or-logic.html&quot;&gt;AND/OR logic&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/attribute-key-matching.html&quot;&gt;Key matching&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/string-value-matching.html&quot;&gt;String value matching&lt;/a&gt; e &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/numeric-value-matching.html&quot;&gt;Numeric value matching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/example-filter-policies.html&quot;&gt;Amazon SNS example filter policies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/message-filtering-apply.html&quot;&gt;Applying a subscription filter policy in Amazon SNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html&quot;&gt;SetSubscriptionAttributes (FilterPolicyScope)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html&quot;&gt;Amazon SNS message attributes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/sns-monitoring-using-cloudwatch.html&quot;&gt;Monitoring Amazon SNS topics using CloudWatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://aws.amazon.com/sns/pricing/&quot;&gt;Amazon SNS pricing&lt;/a&gt; e &lt;a href=&quot;https://aws.amazon.com/sqs/pricing/&quot;&gt;Amazon SQS pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spring Cloud AWS — &lt;a href=&quot;https://docs.awspring.io/spring-cloud-aws/docs/3.4.0/reference/html/index.html#sns-template&quot;&gt;Reference: SNS Template&lt;/a&gt;, código-fonte de &lt;a href=&quot;https://github.com/awspring/spring-cloud-aws/blob/main/spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/core/SnsHeaderConverterUtil.java&quot;&gt;SnsHeaderConverterUtil&lt;/a&gt; (headers viram atributos), &lt;a href=&quot;https://github.com/awspring/spring-cloud-aws/blob/main/spring-cloud-aws-sns/src/main/java/io/awspring/cloud/sns/core/TopicMessageChannel.java&quot;&gt;TopicMessageChannel&lt;/a&gt; (publicação) e &lt;a href=&quot;https://github.com/awspring/spring-cloud-aws/blob/main/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java&quot;&gt;SnsAutoConfiguration&lt;/a&gt; (conversor JSON do &lt;code&gt;SnsTemplate&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>Arquitetura de Software</category><category>AWS</category><category>Mensageria</category></item><item><title>W3C Trace Context — correlacionando logs entre microsserviços com o traceparent</title><link>https://blog.cesarschutz.com.br/posts/w3c-trace-context/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/w3c-trace-context/</guid><description>O padrão W3C que leva o mesmo ID de rastreamento por todos os serviços de uma operação: o traceparent e o tracestate, valores inválidos, a granularidade certa e o ID atravessando o outbox.</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><category>SRE</category><category>Logs</category><category>Microsserviços</category><category>Mensageria</category></item><item><title>AOP no Spring — JDK Dynamic Proxy, CGLIB e aspects customizados</title><link>https://blog.cesarschutz.com.br/posts/aop-jdk-proxy-cglib/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/aop-jdk-proxy-cglib/</guid><description>Como o Spring aplica log, transação e métricas fora da regra de negócio: conceitos de AOP, JDK Dynamic Proxy ou CGLIB (e por que o Boot prefere CGLIB), a self-invocation e aspects próprios.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>Desenvolvimento de Software</category><category>Spring</category><category>AOP</category></item><item><title>AopUtils.getTargetClass() — desembrulhando os proxies do Spring</title><link>https://blog.cesarschutz.com.br/posts/aoputils-gettargetclass/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/aoputils-gettargetclass/</guid><description>Com o bean envolto em proxy, bean.getClass() devolve a classe do proxy e a leitura de anotações falha. Como AopUtils.getTargetClass() recupera a classe real e quando usar ultimateTargetClass().</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>Desenvolvimento de Software</category><category>Spring</category><category>AOP</category></item><item><title>AtomicBoolean — o sinalizador thread-safe da parada graciosa</title><link>https://blog.cesarschutz.com.br/posts/atomicboolean-parada-graciosa/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/atomicboolean-parada-graciosa/</guid><description>Por que um boolean comum pode não ser visto por outra thread, quando volatile basta, por que preferir AtomicBoolean e como ligar o SIGTERM a um job sem encerrar a JVM no meio de um lote.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>Desenvolvimento de Software</category><category>Concorrência</category><category>Kubernetes</category><category>JVM</category></item><item><title>Gradle — quando usar implementation, api, compileOnly e as demais configurações</title><link>https://blog.cesarschutz.com.br/posts/gradle-tipos-de-dependencia/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/gradle-tipos-de-dependencia/</guid><description>Cada configuração de dependência do Gradle alimenta um classpath: compilação, execução, processadores de anotação ou testes. Guia para bibliotecas e starters Spring Boot, com o papel do platform (BOM).</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>Desenvolvimento de Software</category><category>Gradle</category><category>Spring</category></item><item><title>Kubernetes CronJob — concorrência, retries e tempo máximo de execução</title><link>https://blog.cesarschutz.com.br/posts/kubernetes-cronjob-concorrencia/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/kubernetes-cronjob-concorrencia/</guid><description>Os campos que protegem rotinas agendadas: concurrencyPolicy, startingDeadlineSeconds, activeDeadlineSeconds, backoffLimit, restartPolicy e timeZone, e o que eles não garantem.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>DevOps</category><category>Kubernetes</category><category>Concorrência</category></item><item><title>Logging estruturado em Spring Boot — LogstashEncoder vs o suporte nativo do 3.4+</title><link>https://blog.cesarschutz.com.br/posts/logging-estruturado-spring-boot/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/logging-estruturado-spring-boot/</guid><description>Cada log como uma linha JSON pesquisável: o caminho clássico com LogstashEncoder e o suporte nativo do Spring Boot 3.4+ (ECS, Logstash e GELF), com saídas reais, comparativo e critério de escolha.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>SRE</category><category>Spring</category><category>Logs</category><category>Trade-offs</category></item><item><title>SIGTERM e SIGKILL — o ciclo de término de um pod no Kubernetes</title><link>https://blog.cesarschutz.com.br/posts/sigterm-sigkill-kubernetes/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/sigterm-sigkill-kubernetes/</guid><description>Como o Kubernetes encerra um pod: SIGTERM, SIGKILL e grace period, a corrida com os endpoints que o preStop resolve, exit codes, o graceful shutdown do Spring Boot e a pegadinha do PID 1.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>DevOps</category><category>Kubernetes</category><category>Spring</category></item><item><title>Wide events e canonical log lines — a evolução do logging estruturado</title><link>https://blog.cesarschutz.com.br/posts/wide-events-canonical-log-lines/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/wide-events-canonical-log-lines/</guid><description>Um evento rico em contexto por requisição, no lugar de dezenas de logs parciais: as canonical log lines da Stripe, cardinalidade e Observability 2.0, um filtro em Spring Boot e tail sampling.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate><category>SRE</category><category>Logs</category><category>Spring</category></item><item><title>Overhead vs overkill — o custo de toda escolha e o exagero dela</title><link>https://blog.cesarschutz.com.br/posts/overhead-vs-overkill/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/overhead-vs-overkill/</guid><description>Overhead é o custo extra que toda decisão técnica cobra; overkill é a solução desproporcional ao problema. As seis dimensões do overhead e um critério prático para reconhecer overengineering.</description><pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate><category>Arquitetura de Software</category><category>Trade-offs</category><category>Microsserviços</category></item><item><title>JWT — a estrutura e o significado de cada campo</title><link>https://blog.cesarschutz.com.br/posts/jwt-estrutura-e-campos/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/jwt-estrutura-e-campos/</guid><description>As três partes de um JWT, campo a campo: headers JOSE (alg, kid…), claims registradas (iss, sub, exp…), algoritmos de assinatura e cuidados de validação. O payload não é criptografado.</description><pubDate>Sun, 12 Apr 2026 00:00:00 GMT</pubDate><category>Segurança</category><category>JWT</category><category>Criptografia</category></item><item><title>Data lake vs data warehouse — e onde entra o lakehouse</title><link>https://blog.cesarschutz.com.br/posts/data-lake-vs-data-warehouse/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/data-lake-vs-data-warehouse/</guid><description>Schema-on-write vs schema-on-read, ETL vs ELT, dado curado vs dado bruto: o comparativo direto entre Data Warehouse e Data Lake, por que os dois costumam trabalhar juntos e o que o Lakehouse propõe unificar.</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><category>Dados</category><category>Trade-offs</category><category>AWS</category></item><item><title>Guia de atualizações do Java</title><link>https://blog.cesarschutz.com.br/posts/guia-atualizacoes-java/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/guia-atualizacoes-java/</guid><description>Como planejar a migração entre LTS do Java: ciclo de releases, distribuições e licenças, versões mínimas do ecossistema, processo em cinco fases com rollback, segurança, desempenho, containers e CI.</description><pubDate>Mon, 14 Jul 2025 00:00:00 GMT</pubDate><category>Atualizações do Java</category><category>LTS</category><category>Migração</category><category>JVM</category><category>Gradle</category></item><item><title>Java 25 (LTS) — arquivos-fonte compactos, Scoped Values, cache AOT e criptografia pós-quântica</title><link>https://blog.cesarschutz.com.br/posts/java-25/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/java-25/</guid><description>Do Java 22 ao 25, para quem vem do Java 21: arquivos compactos, import module, construtores flexíveis, Scoped Values, cache AOT, headers compactos, criptografia pós-quântica e as 66 JEPs.</description><pubDate>Wed, 02 Jul 2025 02:50:00 GMT</pubDate><category>Atualizações do Java</category><category>LTS</category><category>Linguagem</category><category>JVM</category><category>Criptografia</category></item><item><title>Java 21 (LTS) — virtual threads, pattern matching e Sequenced Collections</title><link>https://blog.cesarschutz.com.br/posts/java-21/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/java-21/</guid><description>O que mudou do Java 17 ao Java 21: virtual threads, pattern matching para switch, record patterns, Sequenced Collections, ZGC geracional e as 38 JEPs do Java 18 ao 21, com a versão em que cada recurso chegou.</description><pubDate>Wed, 02 Jul 2025 02:10:00 GMT</pubDate><category>Atualizações do Java</category><category>LTS</category><category>Linguagem</category><category>Virtual Threads</category><category>Concorrência</category></item><item><title>Java 17 (LTS) — records, sealed classes, text blocks e switch expressions</title><link>https://blog.cesarschutz.com.br/posts/java-17/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/java-17/</guid><description>Do Java 12 ao 17, versão a versão: records, sealed classes, text blocks, switch expressions, pattern matching para instanceof, ZGC e Shenandoah em produção e o que quebra vindo do Java 11.</description><pubDate>Wed, 02 Jul 2025 01:30:00 GMT</pubDate><category>Atualizações do Java</category><category>LTS</category><category>Linguagem</category><category>JVM</category><category>Migração</category></item><item><title>Java 11 (LTS) — módulos, var, HTTP Client e o novo ciclo de releases</title><link>https://blog.cesarschutz.com.br/posts/java-11/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/java-11/</guid><description>O que chegou do Java 9 ao 11 para quem migra do Java 8: sistema de módulos, var, HttpClient, novas APIs, G1 como padrão, TLS 1.3, a remoção do Java EE e do CORBA e o ciclo de releases a cada seis meses.</description><pubDate>Wed, 02 Jul 2025 00:30:00 GMT</pubDate><category>Atualizações do Java</category><category>LTS</category><category>Linguagem</category><category>JVM</category><category>Migração</category></item><item><title>Java 8 (LTS) — lambdas, Stream API, java.time e o fim do PermGen</title><link>https://blog.cesarschutz.com.br/posts/java-8/</link><guid isPermaLink="true">https://blog.cesarschutz.com.br/posts/java-8/</guid><description>O que mudou do Java 7 para o Java 8: lambdas, Stream, Optional, java.time, CompletableFuture e Metaspace no lugar do PermGen, com exemplos antes e depois e a lista completa das 55 JEPs.</description><pubDate>Wed, 02 Jul 2025 00:00:00 GMT</pubDate><category>Atualizações do Java</category><category>LTS</category><category>Linguagem</category><category>JVM</category><category>Concorrência</category></item></channel></rss>