<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cesar Schutz</title><description>Artigos de Cesar Schutz, arquiteto de soluções, sobre arquitetura de software, Java e sistemas de pagamento.</description><link>https://blog.cesarschutz.com.br/</link><language>pt-BR</language><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 esses dados completos.&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, sem alterar as classes e sem mexer no mapper usado pela API.&lt;/p&gt;
&lt;aside class=&quot;aviso&quot; data-aviso=&quot;nota&quot; aria-label=&quot;Nota&quot;&gt;&lt;svg viewBox=&quot;0 0 24 24&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;9&quot;&gt;&lt;/circle&gt;&lt;path d=&quot;M12 11v6M12 7.6v.01&quot;&gt;&lt;/path&gt;&lt;/svg&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.jackson&lt;/code&gt;, o que vem no Spring Boot 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 três coisas, 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, só o nome dele.&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;code&gt;SimpleBeanPropertyFilter&lt;/code&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;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;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;&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;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;/div&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;&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;&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;code&gt;filterOutAllExcept(...)&lt;/code&gt; escreve só os campos listados e &lt;code&gt;filterOutAll()&lt;/code&gt; não escreve nenhum.&lt;/p&gt;
&lt;p&gt;Também dá para passar o provider só na hora de escrever, sem configurá-lo no mapper: &lt;code&gt;mapper.writer(filterProvider).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 precisa conhecer o filtro. Um mapper sem provider falha:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&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;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;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;code&gt;serializeAsProperty&lt;/code&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;&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&quot;&gt;&lt;div class=&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;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&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;em&gt;Diagrama: 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;O diagrama, passo a passo, está no site.&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&gt;O &lt;code&gt;writer&lt;/code&gt; representa a propriedade que está sendo escrita, e &lt;code&gt;writer.getName()&lt;/code&gt; é o nome dela no JSON. A partir daí, o filtro segue um de três caminhos.&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&gt;Para &lt;strong&gt;remover&lt;/strong&gt;, chama &lt;code&gt;serializeAsOmittedProperty&lt;/code&gt;, que é o mesmo que os filtros prontos fazem. Em JSON, isso simplesmente não escreve nada.&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&gt;Para &lt;strong&gt;mascarar&lt;/strong&gt;, lê o valor original e, em vez de delegar ao &lt;code&gt;writer&lt;/code&gt;, escreve ele mesmo o par nome/valor com &lt;code&gt;g.writeStringProperty(...)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&gt;Para &lt;strong&gt;qualquer outro campo&lt;/strong&gt;, chama &lt;code&gt;writer.serializeAsProperty(...)&lt;/code&gt;, o fluxo normal.&lt;/p&gt;&lt;/div&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; (o filtro também é aplicado a mapas, 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;&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;&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;, o filtro não inventa nada 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;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;p&gt;O truque é usar &lt;code&gt;Object.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: toda classe ganha o &lt;code&gt;@JsonFilter&lt;/code&gt;, mas só dentro deste mapper.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&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;&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&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;/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;&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;&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&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;/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;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&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;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;p&gt;Um detalhe do &lt;code&gt;baseBuilder()&lt;/code&gt;: como ele parte de &lt;code&gt;JsonMapper.builder()&lt;/code&gt;, as propriedades &lt;code&gt;spring.jackson.*&lt;/code&gt; do &lt;code&gt;application.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.Builder&lt;/code&gt; que o Spring Boot oferece. Ele já vem com as &lt;code&gt;spring.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 class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&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;&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&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;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&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;&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;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&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;&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&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;/div&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;&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;&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;&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 não quebra os outros mappers, 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;p&gt;&lt;strong&gt;O filtro só age quando o objeto passa pelo mapper.&lt;/strong&gt; Um &lt;code&gt;log.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 record (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 class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&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;Cartao[titular=Cesar, numero=5502091234567890, cvv=123]&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 isso a regra é logar sempre via &lt;code&gt;logJson.toJson(...)&lt;/code&gt;.&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.toJson(&amp;quot;5502091234567890&amp;quot;)&lt;/code&gt; sai inteiro. Se o sistema loga o corpo cru da requisição 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 tem prioridade sobre o mixin 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().setDefaultFilter(filtro)&lt;/code&gt;, que é usado para qualquer id sem registro.&lt;/p&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;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 sempre sai como string 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 um log é um lugar onde ele fica guardado.&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 de 6 a 8 dígitos, 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;&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.jackson.databind&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;com.fasterxml.jackson.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.fasterxml.jackson.annotation&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;com.fasterxml.jackson.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;...databind.ser.std&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;...databind.ser.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;...databind.ser.jdk&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;...databind.ser.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.serializeAsOmittedProperty(...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;writer.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.serializeAsProperty(...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;writer.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.writeStringProperty(nome, valor)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;gen.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.builder().filterProvider(...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;builder().filterProvider(...)&lt;/code&gt; ou &lt;code&gt;mapper.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.WRITE_DATES_AS_TIMESTAMPS&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SerializationFeature.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.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.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.Builder&lt;/code&gt; e as propriedades &lt;code&gt;spring.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 Kubernetes 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;em&gt;onde&lt;/em&gt; essa rotina vai rodar.&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 Spring Batch e termina. O exit code informa ao Kubernetes se deu certo.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/abordagem-a.svg&quot; alt=&quot;Diagrama da abordagem A: a mesma imagem, meu-servico:1.2.3, roda em dois processos; o Deployment da API usa o perfil padrão, com servidor web, e atende HTTP o dia todo; às 03:00, o CronJob cria um Job, que sobe um pod com o perfil batch, que roda só o lote, sem web; o pod lê os pendentes no banco, publica no tópico SNS, marca os registros como enviados e termina, reservando recurso só durante a execução; o exit code volta para o Job, que tenta de novo, até o backoffLimit, se ele for diferente de 0; a API e o job compartilham só o banco&quot;&gt;&lt;/p&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 SQS, 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 o banco diz o que já foi enviado. 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;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/abordagem-b.svg&quot; alt=&quot;Diagrama da abordagem B: o CronJob chama POST /processar num endpoint da API, que publica uma única mensagem no SQS e responde 202 sem ir ao banco; um listener dentro dos mesmos pods da API consome a mensagem, lê os pendentes no banco, publica cada registro no SNS e marca o status; se der erro, a mensagem reaparece na fila depois do visibility timeout e a nova tentativa segue de onde parou; após N recebimentos, ela vai para a DLQ, de onde volta por redrive&quot;&gt;&lt;/p&gt;
&lt;p&gt;A abordagem B não é um antipadrão. 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;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;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;code&gt;SPRING_PROFILES_ACTIVE&lt;/code&gt;, como mostra a seção &lt;a href=&quot;#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;, só impede 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 dividir o mesmo processo:&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 10 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 latência.&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;Isolar recursos por tipo de carga, 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;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;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 tem prazo próprio. 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;code&gt;listenerShutdownTimeout&lt;/code&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, ele é enviado de novo;&lt;/li&gt;
&lt;li&gt;o lote termina em duas versões do código: parte processada pela antiga, parte pela nova.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/deploy-no-meio-do-lote.svg&quot; alt=&quot;Linha do tempo da abordagem B com visibility timeout de 2 horas: às 03:00, o pod v1 recebe a mensagem e processa o lote; às 03:30, um deploy cancela o v1 no meio do lote, sem apagar a mensagem; o pod v2 já está no ar, mas não tem o que consumir, porque a mensagem continua invisível até o visibility timeout expirar, às 05:00; aí ela reaparece, o v2 a recebe e retoma de onde o v1 parou, pelo status no banco; o lote fica parado 1h30 e termina em duas versões do código&quot;&gt;&lt;/p&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;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;). O job de hoje termina com a versão com que começou, 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 não aumenta o heap, 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 4,5 GB 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;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;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 CPU alta significa mais usuários. Com o batch dentro da API, essa premissa quebra:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;o HPA sobe réplicas 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 SNS 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: a retenção 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 10 s, 20 s, 40 s… (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;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/destino-fora-do-ar.svg&quot; alt=&quot;Linha do tempo com o SNS fora do ar das 03:20 às 04:20, no mesmo lote e com maxReceiveCount 3: na abordagem A, o job falha às 03:20, com três tentativas em cerca de um minuto, e os pendentes esperam o próximo dia ou um disparo manual; na B com visibility timeout de 2 horas, a mensagem fica invisível até as 05:00, quando reaparece e o lote retoma e termina; na B com timeout de 1 minuto estendido enquanto processa, três tentativas falham em três minutos, a mensagem vai para a DLQ e os pendentes esperam o redrive ou o próximo disparo; nos três casos o estado fica no banco&quot;&gt;&lt;/p&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 num único ponto da pilha, 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 fica preso a uma mensagem:&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: 12 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;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;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=&quot;true&quot;}&lt;/code&gt; indica o Job que falhou de vez. Não use &lt;code&gt;kube_job_status_failed&lt;/code&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=&quot;enviar-registros&quot;} &gt; 26 * 3600&lt;/code&gt; avisa quando o job diário passa mais de 26 horas 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;#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;code&gt;BATCH_STEP_EXECUTION&lt;/code&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 a resposta se perde no caminho: 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;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/gatilho-dispara-duas-vezes.svg&quot; alt=&quot;Diagrama de sequência: o CronJob faz POST /processar, o endpoint publica a mensagem 1, que a fila standard entrega ao listener, e a execução 1 começa o lote; o endpoint responde 202, mas a resposta se perde na rede; o curl sai com erro, o Kubernetes tenta de novo, o endpoint recebe a segunda chamada e publica a mensagem 2, que vira a execução 2 com a 1 ainda rodando, em outro pod ou no mesmo; as duas processam o mesmo lote ao mesmo tempo, e os registros que ambas leem como pendentes saem duas vezes no SNS&quot;&gt;&lt;/p&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;#x3C;segundos&gt;&lt;/code&gt;.&lt;/p&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 Amazon Builders’ Library 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;p&gt;A coluna de status no banco ajuda, mas não resolve sozinha. 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: o nome do Job é derivado do horário agendado, 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;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/cronjob-vs-endpoint-sqs/sem-resposta-para-perder.svg&quot; alt=&quot;Diagrama de sequência da abordagem A: o CronJob cria o Job enviar-registros-29837160, com nome derivado do horário agendado; a API do Kubernetes responde 201, mas a resposta se perde; a nova tentativa para o mesmo horário usa o mesmo nome e recebe 409 AlreadyExists, sem criar outro Job; o Job, já criado na primeira chamada, 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;/p&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 dois Jobs, ou nenhum, 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;#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 pelo menos uma vez 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 pode voltar 200 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;code&gt;saveState(false)&lt;/code&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;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;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; o problema é consumi-la dentro da API.&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: muitos problemas se resolvem com um job de uma thread e um processo, 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;code&gt;JobOperator.recover(...)&lt;/code&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 tabelas de metadados, 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;&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;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&gt;&lt;strong&gt;A dependência.&lt;/strong&gt; No Spring Boot 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 class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&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;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-batch-jdbc&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;p&gt;As tabelas precisam existir no banco. Por padrão (&lt;code&gt;spring.batch.jdbc.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 &quot;batch_job_instance&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.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;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(&quot;batch&quot;)&lt;/code&gt;. O &lt;code&gt;application.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.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;&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;&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;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;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(&quot;!batch&quot;)&lt;/code&gt;.&lt;/p&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;&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&quot;&gt;&lt;div class=&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;&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;&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;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&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.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.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 são ignorados (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;&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;&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;&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;-&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;&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;&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;&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;&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 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;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;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.springframework.batch.infrastructure.item&lt;/code&gt;); o step precisa de &lt;code&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;&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;&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;&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;&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;&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;-&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;&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;&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;&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;&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;#x3C;&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;&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;&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;&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;#x3C;&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;&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;#x3C;&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;&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;#x3C;&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;&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&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;&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;&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;&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;&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;&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;&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;&quot;&lt;/span&gt;&lt;span style=&quot;--0:#2F6B4F;--1:#86C3A2&quot;&gt;WHERE status = &apos;PENDENTE&apos;&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;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;&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; 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;#x3C;&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;&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;-&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;&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;&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;&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;&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;#x3C;&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;&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;-&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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&quot;&gt;&lt;div class=&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;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&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;&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;&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&gt;
&lt;li&gt;&lt;code&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&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&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&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.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;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;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.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, a abordagem A vence nos critérios que mais pesam: 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;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;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.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.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;#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;#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.net.http.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.Version.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;&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.H3_DISCOVERY&lt;/code&gt; com &lt;code&gt;Http3DiscoveryMode.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.H3_DISCOVERY&lt;/code&gt; com &lt;code&gt;Http3DiscoveryMode.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.google.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;&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.net.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.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.plusSaturating(Duration)&lt;/code&gt; soma sem estourar: no limite, devolve &lt;code&gt;Instant.MIN&lt;/code&gt; ou &lt;code&gt;Instant.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.BodyPublishers.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.nio.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;&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.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.Option.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.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;&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;&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;.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;&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.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.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.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.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.net.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.tls.namedGroups&lt;/code&gt; ou &lt;code&gt;SSLParameters.setNamedGroups&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&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;&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.crypto.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.setAccessible(true)&lt;/code&gt; seguido de &lt;code&gt;Field.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;#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;&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;&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.FinalFieldMutation&lt;/code&gt;. Para bibliotecas de serialização, a JEP recomenda &lt;code&gt;sun.reflect.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.applet&lt;/code&gt; inteiro, &lt;code&gt;javax.swing.JApplet&lt;/code&gt;, &lt;code&gt;java.beans.AppletInitializer&lt;/code&gt; e os membros de &lt;code&gt;java.beans.Beans&lt;/code&gt; e &lt;code&gt;javax.swing.RepaintManager&lt;/code&gt; que dependiam deles. Um efeito colateral: &lt;code&gt;URL.getContent()&lt;/code&gt; e &lt;code&gt;URLConnection.getContent()&lt;/code&gt; não devolvem mais &lt;code&gt;java.applet.AudioClip&lt;/code&gt; para conteúdo de áudio. Para tocar áudio, a JEP aponta a &lt;code&gt;javax.sound.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;&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.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.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.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.internal.vm.ci&lt;/code&gt;, &lt;code&gt;jdk.graal.compiler&lt;/code&gt; e &lt;code&gt;jdk.graal.compiler.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.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.lang.Process.launchMechanism&lt;/code&gt; (Linux) e a propriedade &lt;code&gt;java.locale.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.net.SocketPermission&lt;/code&gt; e &lt;code&gt;Socket.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.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;&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.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;&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;&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.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;&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;&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.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;&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.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.lang.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;#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.ofLazy&lt;/code&gt;, &lt;code&gt;Map.ofLazy&lt;/code&gt; e, a partir do Java 27, &lt;code&gt;Set.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;&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.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;&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.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.ofLazy&lt;/code&gt; e &lt;code&gt;Map.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.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;#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.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;&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.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.withFactory&lt;/code&gt; virou &lt;code&gt;withFactoriesOf&lt;/code&gt;, e entrou a exceção não verificada &lt;code&gt;javax.crypto.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;&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.incubator.vector SomaVetorial.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.incubator.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;#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;#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;#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;#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;#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;#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;#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.stop()&lt;/code&gt;, a Applet API e &lt;code&gt;ThreadPoolExecutor.finalize()&lt;/code&gt;. No último caso, quem sobrescrevia &lt;code&gt;finalize()&lt;/code&gt; chamando &lt;code&gt;super.finalize()&lt;/code&gt; passa a chamar &lt;code&gt;Object.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.Builder.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.httpserver.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.net.httpserver.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.tls.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.toString&lt;/code&gt; (&lt;code&gt;-Djdk.compat.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.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.rmi.ssl.client.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.tls.SunX509KeyManager.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;&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;&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;&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.incubator.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.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;&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;&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;&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;&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;&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.persistence.lock.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;&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;&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;&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.threads.virtual.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.tomcat.threads.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;&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;&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.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.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.dump_to_file -format=text dump.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.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.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.jfr ...&lt;/code&gt; e depois &lt;code&gt;jfr print --events jdk.VirtualThreadPinned rec.jfr&lt;/code&gt;. No &lt;code&gt;CarrierPresa.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.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;&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.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.threads.virtual.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.tomcat.threads.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.java&lt;/code&gt; no Java 21 ou mais novo, sem dependência nenhuma. O &lt;code&gt;Thread.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;&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;&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;&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;&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;&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;&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.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;&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;&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;&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;&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.retry.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.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.jfr.consumer.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.threads.virtual.enabled&lt;/code&gt;, &lt;code&gt;server.tomcat.threads.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;&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;&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;&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;&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;Um timeout não diz se a operação aconteceu. 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; POST não é. 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;strong&gt;onde&lt;/strong&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 tabela vazia e as duas cobram.&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;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;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 verificar e gravar passam a ser a mesma operação. Role devagar: a lousa acompanha a leitura e avança um passo a cada parágrafo.&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;O diagrama, passo a passo, está no site.&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&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;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&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;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&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;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&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;/p&gt;&lt;/div&gt;&lt;div class=&quot;passo&quot;&gt;&lt;p&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;/p&gt;&lt;/div&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;&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;&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&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;/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;&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;&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;code&gt;422 Unprocessable Content&lt;/code&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 mesma transação 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 seja sucesso ou falha, 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 o que chegou a ser gravado. 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 “consulta, depois grava”.&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;&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;&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;&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;&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;&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;&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;&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;&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;&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;&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.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;&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;&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;&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;&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;&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.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;&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><content:encoded>&lt;p&gt;Quando uma operação passa por vários serviços, cada um grava seus próprios logs. Sem um identificador comum, reconstruir o que aconteceu com &lt;strong&gt;uma&lt;/strong&gt; operação vira garimpo: buscar por horário, por ID de cliente, torcer para os relógios baterem. E se cada ferramenta de tracing usa um header próprio, o ID se perde na primeira fronteira entre fornecedores.&lt;/p&gt;
&lt;p&gt;O &lt;strong&gt;W3C Trace Context&lt;/strong&gt; resolve isso. É uma recomendação do W3C que padroniza como o contexto de rastreamento (quem é a operação e de onde veio a chamada) é propagado entre serviços, de forma que qualquer ferramenta entenda. O campo central é o &lt;code&gt;traceparent&lt;/code&gt;: com o valor dele em mãos, uma única busca na ferramenta de observabilidade mostra tudo o que aconteceu com a operação, do serviço que a originou até o último consumidor.&lt;/p&gt;
&lt;p&gt;Este post mostra a anatomia do &lt;code&gt;traceparent&lt;/code&gt; e do &lt;code&gt;tracestate&lt;/code&gt;, os valores que a especificação considera inválidos, a granularidade certa para jobs em lote e como o ID atravessa um fluxo assíncrono com outbox pattern e SNS.&lt;/p&gt;
&lt;h2 id=&quot;trace-span-e-os-ids-do-traceparent&quot;&gt;Trace, span e os IDs do traceparent&lt;/h2&gt;
&lt;p&gt;Dois termos antes de começar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Trace&lt;/strong&gt;: a operação inteira, com todos os passos em todos os serviços.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Span&lt;/strong&gt;: um passo dentro do trace (uma requisição recebida, uma consulta, uma publicação de mensagem). Um serviço pode gerar vários spans no mesmo trace.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O &lt;code&gt;traceparent&lt;/code&gt; carrega dois IDs que importam para a correlação:&lt;/p&gt;
&lt;div class=&quot;tabela&quot; tabindex=&quot;0&quot;&gt;



















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;ID&lt;/th&gt;&lt;th&gt;O que é&lt;/th&gt;&lt;th&gt;Exemplo de uso&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;trace-id&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;ID da operação inteira, o mesmo em todos os serviços&lt;/td&gt;&lt;td&gt;“me mostre tudo sobre esse lote específico”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;parent-id&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;ID do span de quem fez a chamada (muitas ferramentas chamam de &lt;strong&gt;span-id&lt;/strong&gt;); cada passo gera o seu&lt;/td&gt;&lt;td&gt;saber de qual passo veio a chamada que gerou um log&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Além deles, o header traz a versão do formato e as flags de rastreamento.&lt;/p&gt;
&lt;h2 id=&quot;anatomia-do-traceparent&quot;&gt;Anatomia do traceparent&lt;/h2&gt;
&lt;p&gt;O valor tem quatro campos separados por hífen, sempre em hexadecimal minúsculo. Este é o exemplo da própria especificação:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;traceparent&lt;/span&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;00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01&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;tabela&quot; tabindex=&quot;0&quot;&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Campo&lt;/th&gt;&lt;th&gt;Tamanho&lt;/th&gt;&lt;th&gt;Valor no exemplo&lt;/th&gt;&lt;th&gt;O que significa&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;&lt;td&gt;2 caracteres (1 byte)&lt;/td&gt;&lt;td&gt;&lt;code&gt;00&lt;/code&gt;&lt;/td&gt;&lt;td&gt;versão do formato; a atual é &lt;code&gt;00&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;trace-id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;32 caracteres (16 bytes)&lt;/td&gt;&lt;td&gt;&lt;code&gt;4bf92f3577b34da6a3ce929d0e0e4736&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ID do trace, igual em todos os serviços&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;parent-id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;16 caracteres (8 bytes)&lt;/td&gt;&lt;td&gt;&lt;code&gt;00f067aa0ba902b7&lt;/code&gt;&lt;/td&gt;&lt;td&gt;ID do span de quem chamou&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;trace-flags&lt;/code&gt;&lt;/td&gt;&lt;td&gt;2 caracteres (8 bits)&lt;/td&gt;&lt;td&gt;&lt;code&gt;01&lt;/code&gt;&lt;/td&gt;&lt;td&gt;flags; hoje só o bit &lt;code&gt;sampled&lt;/code&gt; é definido&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;No total são 55 caracteres. A recomendação é enviar o nome do header em minúsculas (&lt;code&gt;traceparent&lt;/code&gt;), e quem recebe precisa aceitá-lo em qualquer caixa.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;As flags são bits, não um número.&lt;/strong&gt; O único bit definido é o menos significativo, &lt;code&gt;sampled&lt;/code&gt; (amostrado): ligado, indica que quem chamou pode ter gravado os dados do trace; desligado (&lt;code&gt;00&lt;/code&gt;), que não gravou. Como é um campo de bits, a leitura correta usa máscara (&lt;code&gt;flags &amp;#x26; 0x01&lt;/code&gt;), não comparação com &lt;code&gt;01&lt;/code&gt;. Os demais bits são reservados e devem ir zerados.&lt;/p&gt;
&lt;p&gt;A cada salto, o serviço repassa o &lt;code&gt;trace-id&lt;/code&gt; intacto e normalmente troca o &lt;code&gt;parent-id&lt;/code&gt; pelo ID do próprio span. É isso que permite montar a árvore de chamadas: o &lt;code&gt;trace-id&lt;/code&gt; agrupa, o &lt;code&gt;parent-id&lt;/code&gt; encadeia.&lt;/p&gt;
&lt;h3 id=&quot;valores-inválidos&quot;&gt;Valores inválidos&lt;/h3&gt;
&lt;p&gt;A especificação define quando o &lt;code&gt;traceparent&lt;/code&gt; não vale:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Versão &lt;code&gt;ff&lt;/code&gt;&lt;/strong&gt;: proibida.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;trace-id&lt;/code&gt; só com zeros&lt;/strong&gt; (&lt;code&gt;00000000000000000000000000000000&lt;/code&gt;): inválido.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;parent-id&lt;/code&gt; só com zeros&lt;/strong&gt; (&lt;code&gt;0000000000000000&lt;/code&gt;): inválido.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caracteres fora do hexadecimal minúsculo&lt;/strong&gt; (letras maiúsculas, por exemplo) ou tamanho errado: inválido.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Diante de um valor inválido, o serviço deve ignorar o &lt;code&gt;traceparent&lt;/code&gt; recebido: começa um trace novo e descarta o &lt;code&gt;tracestate&lt;/code&gt;. Na prática, não gere esses valores à mão. Use a biblioteca de tracing (o OpenTelemetry já usa o W3C Trace Context como propagador padrão). A especificação recomenda que o &lt;code&gt;trace-id&lt;/code&gt; seja aleatório e globalmente único, e proíbe usar dados do usuário (como o IP) como semente.&lt;/p&gt;
&lt;h2 id=&quot;o-tracestate&quot;&gt;O tracestate&lt;/h2&gt;
&lt;p&gt;A especificação define um segundo header, o &lt;code&gt;tracestate&lt;/code&gt;, para informações específicas de cada fornecedor de tracing. É uma lista de pares &lt;code&gt;chave=valor&lt;/code&gt; separados por vírgula, com no máximo 32 itens:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;tracestate&lt;/span&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;rojo=00f067aa0ba902b7,congo=t61rcWkgMzE&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;Ele sempre acompanha o &lt;code&gt;traceparent&lt;/code&gt;: um &lt;code&gt;tracestate&lt;/code&gt; recebido sem &lt;code&gt;traceparent&lt;/code&gt; é descartado, e se o &lt;code&gt;traceparent&lt;/code&gt; for inválido o &lt;code&gt;tracestate&lt;/code&gt; nem é lido. Para correlacionar logs, o &lt;code&gt;traceparent&lt;/code&gt; sozinho basta. O &lt;code&gt;tracestate&lt;/code&gt; só importa quando mais de uma ferramenta de tracing participa do mesmo fluxo.&lt;/p&gt;
&lt;p&gt;Os dois campos existem apenas para correlação: a especificação proíbe colocar neles dados pessoais ou sensíveis.&lt;/p&gt;
&lt;h2 id=&quot;fora-do-http-o-traceparent-em-mensagens&quot;&gt;Fora do HTTP: o traceparent em mensagens&lt;/h2&gt;
&lt;p&gt;A especificação define o formato para headers HTTP. Outros protocolos têm especificações de extensão, e em mensageria o caminho usual é levar o mesmo valor como metadado da mensagem. No SNS, isso é um &lt;strong&gt;MessageAttribute&lt;/strong&gt; (metadado enviado junto com a mensagem, fora do corpo; veja o post sobre &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/sns-filter-policy/&quot;&gt;SNS MessageAttributes e Filter Policy&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;As convenções semânticas de mensageria do OpenTelemetry chamam isso de &lt;strong&gt;contexto de criação da mensagem&lt;/strong&gt;: o produtor cria o contexto e ele deve ser propagado com a mensagem até os consumidores. Sem isso, os traces do consumidor não se ligam diretamente aos do produtor.&lt;/p&gt;
&lt;h2 id=&quot;granularidade-importa-por-lote-não-por-execução&quot;&gt;Granularidade importa: por lote, não por execução&lt;/h2&gt;
&lt;p&gt;Um job que processa 50 lotes poderia usar o mesmo trace-id para todos (um trace por execução do job). Mas isso mistura os logs de todos os lotes: se o lote #47 falhar no consumidor, não dá para isolá-lo. A abordagem recomendada é gerar um &lt;strong&gt;trace-id por lote&lt;/strong&gt; (por evento de outbox). Cada evento gravado na tabela de outbox tem seu próprio &lt;code&gt;traceparent&lt;/code&gt;, que viaja com a mensagem até o consumidor.&lt;/p&gt;
&lt;p&gt;Para correlacionar todos os lotes de uma mesma execução (“quantos lotes rodaram na execução das 02h?”), use um &lt;strong&gt;job-run-id&lt;/strong&gt; separado no MDC (o contexto de log por thread do SLF4J/Logback), sem misturar com o trace-id do evento. São duas perguntas diferentes, respondidas por dois IDs diferentes. Se a ferramenta for o OpenTelemetry, dá para registrar também essa relação entre traces com &lt;strong&gt;span links&lt;/strong&gt;, que associam um span a um ou mais spans, inclusive de outros traces, indicando relação de causa.&lt;/p&gt;
&lt;h2 id=&quot;como-o-outbox-pattern-usa-na-prática&quot;&gt;Como o outbox pattern usa na prática&lt;/h2&gt;
&lt;p&gt;O &lt;strong&gt;outbox pattern&lt;/strong&gt; grava o evento numa tabela do próprio banco (a tabela outbox), na mesma transação da mudança de estado. Um processo separado, o &lt;strong&gt;relay&lt;/strong&gt;, lê essa tabela e publica os eventos no broker (detalhes no 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;). O &lt;code&gt;traceparent&lt;/code&gt; vai junto com o evento em cada etapa:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.cesarschutz.com.br/posts/w3c-trace-context/propagacao-traceparent.svg&quot; alt=&quot;O traceparent gravado no outbox viaja pelo relay e SNS até o MDC do consumidor&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;O job produtor inicia um trace novo &lt;strong&gt;por lote&lt;/strong&gt; e grava o &lt;code&gt;traceparent&lt;/code&gt; junto do evento na tabela de outbox.&lt;/li&gt;
&lt;li&gt;O relay lê o evento e o &lt;code&gt;traceparent&lt;/code&gt; da tabela.&lt;/li&gt;
&lt;li&gt;O relay publica no SNS com &lt;code&gt;PublishBatch&lt;/code&gt; (até 10 mensagens por chamada), levando o &lt;code&gt;traceparent&lt;/code&gt; como &lt;code&gt;MessageAttribute&lt;/code&gt; de cada mensagem.&lt;/li&gt;
&lt;li&gt;O SNS entrega na fila SQS. O consumidor lê o atributo, continua o mesmo trace e coloca o trace-id e o span-id no MDC. Todos os logs dele saem com esses campos.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Com isso, a ferramenta de observabilidade monta a linha do tempo produtor → mensageria → consumidor com uma busca só pelo trace-id. Para os campos do MDC aparecerem como campos pesquisáveis no log, emita logs estruturados (veja &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/logging-estruturado-spring-boot/&quot;&gt;Logging estruturado em Spring Boot&lt;/a&gt;). O mesmo &lt;code&gt;trace_id&lt;/code&gt; também pode ligar um &lt;a href=&quot;https://blog.cesarschutz.com.br/posts/wide-events-canonical-log-lines/&quot;&gt;wide event&lt;/a&gt; ao trace distribuído.&lt;/p&gt;
&lt;p&gt;Cuidados nesse fluxo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raw message delivery&lt;/strong&gt;: com a entrega bruta desligada (o padrão), a mensagem chega ao SQS dentro do envelope JSON do SNS, e os atributos vêm no campo &lt;code&gt;MessageAttributes&lt;/code&gt; desse JSON. Com ela ligada, os atributos chegam como atributos da própria mensagem SQS, mas o limite é de 10: mensagens com mais atributos que isso são descartadas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nomes no MDC&lt;/strong&gt;: o agente Java do OpenTelemetry já injeta &lt;code&gt;trace_id&lt;/code&gt;, &lt;code&gt;span_id&lt;/code&gt; e &lt;code&gt;trace_flags&lt;/code&gt; no MDC do Logback e do Log4j. Se você preencher o MDC à mão, use os mesmos nomes em todos os serviços, ou a busca não junta os logs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;fontes&quot;&gt;Fontes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;W3C — &lt;a href=&quot;https://www.w3.org/TR/trace-context/&quot;&gt;Trace Context (W3C Recommendation, 23/11/2021)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenTelemetry — &lt;a href=&quot;https://opentelemetry.io/docs/concepts/context-propagation/&quot;&gt;Context Propagation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenTelemetry — &lt;a href=&quot;https://opentelemetry.io/docs/concepts/signals/traces/&quot;&gt;Traces: Span Context e Span Links&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenTelemetry — &lt;a href=&quot;https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/&quot;&gt;Semantic conventions for messaging spans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenTelemetry Java Instrumentation — &lt;a href=&quot;https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/logger-mdc-instrumentation.md&quot;&gt;Logger MDC auto-instrumentation&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-large-payload-raw-message-delivery.html&quot;&gt;Amazon SNS raw message delivery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/dg/http-notification-json.html&quot;&gt;HTTP/HTTPS notification JSON format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AWS — &lt;a href=&quot;https://docs.aws.amazon.com/sns/latest/api/API_PublishBatch.html&quot;&gt;PublishBatch (Amazon SNS API Reference)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><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>