<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joel Filho</title>
    <description>The latest articles on DEV Community by Joel Filho (@joelbrs).</description>
    <link>https://dev.to/joelbrs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1061588%2F924c67c7-dffa-47c5-b266-942517458454.jpeg</url>
      <title>DEV Community: Joel Filho</title>
      <link>https://dev.to/joelbrs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joelbrs"/>
    <language>en</language>
    <item>
      <title>Idempotência: Melhorando a Resiliência de Seu Sistema - Parte II</title>
      <dc:creator>Joel Filho</dc:creator>
      <pubDate>Sun, 21 Jul 2024 23:40:15 +0000</pubDate>
      <link>https://dev.to/joelbrs/idempotencia-melhorando-a-resiliencia-de-seu-sistema-parte-ii-4p6k</link>
      <guid>https://dev.to/joelbrs/idempotencia-melhorando-a-resiliencia-de-seu-sistema-parte-ii-4p6k</guid>
      <description>&lt;p&gt;No &lt;a href="https://dev.to/joelbrs/idempotencia-melhorando-a-resiliencia-de-seu-sistema-parte-i-1c99"&gt;post anterior&lt;/a&gt;, discutimos os conceitos básicos de Resiliência e Idempotência. Além disso, demonstrei como apliquei esses conceitos de forma prática em um projeto pessoal.&lt;/p&gt;

&lt;p&gt;Agora, explorarei algumas limitações do modelo inicialmente proposto e apresentarei uma alternativa viável para implementar idempotência, que é mais performática.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quais são as limitações de gerar a Chave de Idempotência no Front-end?
&lt;/h2&gt;

&lt;p&gt;No modelo proposto anteriormente, a chave de idempotência é gerada pelo front-end, armazenada no SessionStorage do navegador e posteriormente enviada ao back-end. Embora essa abordagem funcione, não é a mais adequada para resolver o problema.&lt;/p&gt;

&lt;p&gt;Primeiramente, a geração da chave pelo front-end permite que o usuário do sistema a manipule, já que é facilmente acessível ao abrir a aba de armazenamento do navegador.&lt;/p&gt;

&lt;p&gt;Em segundo lugar, e estritamente relacionado ao primeiro ponto, como o front-end está mais suscetível a manipulações e ataques cibernéticos. Por padrão, regras de negócio não devem ser estabelecidas no front-end. Caso haja necessidade, elas devem ser reforçadas no back-end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qual seria a solução?
&lt;/h2&gt;

&lt;p&gt;A primeira solução, mais simples, seria criar um endpoint no back-end para gerar a chave de idempotência e armazená-la em memória. Nesse caso, poderíamos utilizar a abordagem de gerar um UUID como chave de idempotência.&lt;/p&gt;

&lt;p&gt;A segunda, mais robusta, é utilizar uma camada de cache para armazenar a chave de idempotência por um tempo pré-estabelecido. Nesse caso, a chave de idempotência poderia ser criada a partir de um hash das informações da conta do remetente, do destinatário, do valor e da descrição (se houver). Essa chave seria armazenada em um Redis, por exemplo, por 5 minutos (ou qualquer outro período de tempo, dependendo da implementação). Caso a requisição se repita devido a alguma instabilidade, a chave será buscada no cache e a transação será encontrada.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Na segunda proposta, não optei por gerar um UUID a cada transação. Isso se deve ao fato de que, se um UUID for gerado a cada requisição para criar uma transação, mesmo que uma requisição seja duplicada, ainda assim seriam duas requisições diferentes, resultando em UUIDs distintos. Dessa forma, nossa chave de idempotência não seria verdadeiramente idempotente.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Por que essa é uma melhor solução?
&lt;/h2&gt;

&lt;p&gt;Primeiro, porque eliminamos a necessidade de um campo correspondente à chave de idempotência no banco de dados, evitando sobrecarregar o banco de dados principal com consultas para verificar se a transação já existe. A consulta ao Redis é muito mais rápida, performática e menos custosa.&lt;/p&gt;

&lt;p&gt;Segundo, porque retiramos qualquer regra de negócio do front-end, evitando assim que nosso sistema esteja mais vulnerável a ataques e manipulações indesejadas dos dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como implementar essa solução?
&lt;/h2&gt;

&lt;p&gt;Primeiro, vamos instalar o Redis no nosso projeto NodeJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pnpm&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="nx"&gt;ioredis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos criar uma instância do Redis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Redis&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ioredis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos criar o hash que será nossa chave de idempotência:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataToBeHashed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;senderAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;receiverAccount&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idempotentKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataToBeHashed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, definimos essa chave de idempotência no cache e verificamos sua existência:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idempotentKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingTransaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta foi uma demonstração simples de como essa abordagem pode ser implementada com NodeJS, independentemente do framework utilizado, seja Express, NestJS, Koa ou Fastify.&lt;/p&gt;

&lt;p&gt;Essa implementação ainda não está disponível no repositório do projeto, mas pretendo trabalhar nisso nos próximos dias.&lt;/p&gt;

&lt;p&gt;Esta série de posts foi criada para compartilhar minha jornada no desenvolvimento deste projeto e as decisões que tomei com base em meus estudos e reflexões.&lt;/p&gt;

&lt;p&gt;Estou aberto a feedbacks e novas propostas. Pretendo implementar novas features futuramente, então estou à disposição para conversar mais sobre isso no meu &lt;a href="https://linkedin.com/in/joelbrs" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Idempotência: Melhorando a Resiliência de Seu Sistema - Parte I</title>
      <dc:creator>Joel Filho</dc:creator>
      <pubDate>Sun, 21 Jul 2024 23:39:03 +0000</pubDate>
      <link>https://dev.to/joelbrs/idempotencia-melhorando-a-resiliencia-de-seu-sistema-parte-i-1c99</link>
      <guid>https://dev.to/joelbrs/idempotencia-melhorando-a-resiliencia-de-seu-sistema-parte-i-1c99</guid>
      <description>&lt;p&gt;À medida que seu software cresce, é crucial aplicar dois conceitos fundamentais no desenvolvimento: &lt;em&gt;Resiliência&lt;/em&gt; e &lt;em&gt;Idempotência&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Esses conceitos trabalham juntos em harmonia. Hoje, vou apresentar uma breve introdução a esses conceitos e compartilhar como os apliquei de forma prática em meu projeto de simulação bancária, onde implementei a criação de transações entre diferentes contas de forma idempotente.&lt;/p&gt;

&lt;p&gt;Confira o projeto no meu GitHub e no repositório &lt;a href="https://github.com/joelbrs/bank.com.br" rel="noopener noreferrer"&gt;bank.com.br&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resiliência
&lt;/h2&gt;

&lt;p&gt;Resiliência é a capacidade do seu software de falhar e lidar bem com essas falhas. Para desenvolver um software resiliente, a equipe deve antecipar possíveis falhas e planejar como resolvê-las. Todos os sistemas estão sujeitos a falhas, mas o que os diferencia é a capacidade de tratar e resolver esses problemas de maneira eficiente. =)&lt;/p&gt;

&lt;h2&gt;
  
  
  Idempotência
&lt;/h2&gt;

&lt;p&gt;Idempotência é a propriedade que algumas operações têm de poderem ser aplicadas várias vezes sem alterar o resultado após a aplicação inicial. Em outras palavras, uma operação idempotente pode ser repetida inúmeras vezes e o estado do sistema permanecerá o mesmo.&lt;/p&gt;

&lt;p&gt;Por exemplo, no contexto da aplicação desenvolvida, a idempotência foi aplicada no seguinte cenário: Digamos que uma conta A está fazendo uma transação de R$10,00 para a conta B. Porém, por uma inconsistência nos servidores, essa transação foi realizada duas vezes, fazendo com que o valor enviado para a conta B dobrasse para R$20,00. Isso representa um problema significativo, especialmente em transações maiores. A idempotência pode ser aplicada para prevenir essas duplicações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas como aplicar esses conceitos, na prática?
&lt;/h2&gt;

&lt;p&gt;Recentemente, trabalhei em um projeto pessoal, o Bank, onde a proposta foi simular o dia-a-dia de um banco, realizando transações entre diferentes contas. As tecnologias utilizadas no projeto foram: React, Relay, GraphQL, KoaJS e MongoDB.&lt;/p&gt;

&lt;p&gt;Primeiramente, criei o model utilizando o mongoose, referente às contas que seriam criadas no sistema, contendo as seguintes informações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identificador Único da Conta&lt;/li&gt;
&lt;li&gt;Número da Conta&lt;/li&gt;
&lt;li&gt;O CPF/CNPJ (taxId) do usuário&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em seguida, foi criado o model das transações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identificador Único da Transação&lt;/li&gt;
&lt;li&gt;O identificador da conta do remetente&lt;/li&gt;
&lt;li&gt;O identificador da conta do destinatário&lt;/li&gt;
&lt;li&gt;O valor a ser transferido&lt;/li&gt;
&lt;li&gt;Chave de Impotência&lt;/li&gt;
&lt;li&gt;Descrição da Transação (Opcional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Podemos perceber, no model de Transação, que há um campo chamado “Chave de Idempotência”. A criação e utilização desse campo no nosso banco de dados representa a estratégia de idempotência utilizada no desenvolvimento do sistema. Existem algumas estratégias para isso, como: Idempotency Key (padrão utilizado), Get Or Create, Histórico de Chamadas, dentre outros.&lt;/p&gt;

&lt;p&gt;De forma geral, será gerada uma Chave de Idempotência (única) para verificar se uma transação já foi realizada anteriormente. A Chave de Idempotência deve ser única para o contexto específico de uma transação. Em uma transação, temos informações que definem seu contexto, como a conta do remetente, a conta do destinatário e o valor. Isso significa que a chave de idempotência deve ser única para uma transação que envolva essas informações. &lt;em&gt;Para uma discussão detalhada sobre o assunto, acesse a seguinte &lt;a href="https://github.com/joelbrs/bank.com.br/issues/12" rel="noopener noreferrer"&gt;issue&lt;/a&gt; do repositório do projeto, criada pelo &lt;a href="https://github.com/caiocampoos" rel="noopener noreferrer"&gt;@caiocampoos&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para implementar isso, defini um índice composto no meu Schema, entre essas informações:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;TransactionSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;senderAccountId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;idempotentKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;receiverAccountId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para receber essa Chave de Idempotência, optei por recebê-la no header "idempotentkey". Essa escolha será discutida mais detalhadamente em uma publicação futura.&lt;/p&gt;

&lt;p&gt;Agora, na criação da Transação, fiz a seguinte verificação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingTransaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;TransactionModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="nx"&gt;idempotentKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;senderAccountId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;senderAccount&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;receiverAccountId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;receiverAccount&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingTransaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;existingTransaction&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observe que retorno o identificador da transação criada anteriormente com as mesmas informações, mas também poderia lançar uma exceção. Tudo depende do contexto da aplicação e de qual abordagem é a melhor para você.&lt;/p&gt;

&lt;p&gt;Para criar a chave de idempotência no front-end da aplicação, escrevi o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;v7&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;uuid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createIdempotencyKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idempotencyKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idempotent-key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idempotencyKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Armazenei a Chave de Idempotência no SessionStorage do navegador quando o usuário decide criar uma transação e, ao fazer a requisição, pego esse valor e envio no cabeçalho para o back-end. Dessa forma, garanto que essa Chave de Idempotência seja utilizada apenas naquele contexto, visto que, diferentemente do LocalStorage, esse dado só estará disponível para aquela sessão enquanto ela existir (ou até a informação ser sobrescrita).&lt;/p&gt;

&lt;p&gt;Porém, pesquisando um pouco mais e refletindo melhor sobre essas ideias, conclui que essa abordagem pode ter certas limitações, que trataremos no próximo post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fontes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Idempotent" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Glossary/Idempotent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.openpix.com.br/docs/concepts/idempotence" rel="noopener noreferrer"&gt;https://developers.openpix.com.br/docs/concepts/idempotence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gooddata.com/blog/multi-tenant-architecture/" rel="noopener noreferrer"&gt;https://www.gooddata.com/blog/multi-tenant-architecture/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/joelbrs/bank.com.br" rel="noopener noreferrer"&gt;https://github.com/joelbrs/bank.com.br&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Guia de Introdução ao Docker</title>
      <dc:creator>Joel Filho</dc:creator>
      <pubDate>Sun, 09 Apr 2023 00:53:10 +0000</pubDate>
      <link>https://dev.to/joelbrs/guia-de-introducao-ao-docker-4eno</link>
      <guid>https://dev.to/joelbrs/guia-de-introducao-ao-docker-4eno</guid>
      <description>&lt;p&gt;Quando falamos de &lt;em&gt;Docker&lt;/em&gt;, uma das primeiras coisas que nos vem à mente são &lt;em&gt;containers&lt;/em&gt;. Basicamente, quase tudo em Docker se resume a containers, então, é super importante que você tenha esse conceito bem sólido na sua mente e não só isso, mas também como funcionam.&lt;/p&gt;




&lt;h2&gt;
  
  
  Como funcionam os containers?
&lt;/h2&gt;

&lt;p&gt;Para explicar o conceito de containers, podemos começar pelo sistema operacional (SO) - tendo como base para a explicação o Linux, especificamente - ser composto de processos e subprocessos. Para entender melhor esse conceito, precisamos entender os três principais pilares que os sustentam: &lt;em&gt;Namespaces&lt;/em&gt;, &lt;em&gt;CGroups _e _Overlay File System&lt;/em&gt; (OFS) que falaremos a seguir.&lt;/p&gt;

&lt;h3&gt;
  
  
  Namespaces:
&lt;/h3&gt;

&lt;p&gt;A partir desses processos, surgiu os chamados &lt;em&gt;Namespaces&lt;/em&gt;, que, basicamente, atuam no &lt;strong&gt;isolamento&lt;/strong&gt; de cada processo. Nesse caso, há uma hierarquia entre os processos-pai e os processos-filhos, onde estes últimos são altamente dependentes dos primeiros e, caso aconteça algo aos processos principais, todo o meu sistema operacional vai à baixo. Tendo isso em mente, os Namespaces isolam cada processo do SO, permitindo que cada um rode de forma independente. Em outras palavras, um container emula um SO com processos rodando em isolamento e executando tarefas diferentes. Containers não executam um SO completo, mas apenas os elementos específicos necessários, incluindo o kernel.&lt;/p&gt;

&lt;h3&gt;
  
  
  CGroups:
&lt;/h3&gt;

&lt;p&gt;Para entender o funcionamento do &lt;strong&gt;CGroups&lt;/strong&gt; e para quê eles servem, pensemos na seguinte ocorrência: Temos alguns containers rodando (sabendo que containers são, basicamente, processos isolados que possuem subprocessos) e, em um deles, temos um enorme vazamento (leak) de memória, o que consequentemente acaba afetando os outros processos fora desse &lt;em&gt;Namespace&lt;/em&gt;. É aí que entram os CGroups. Eles surgiram para controlar e isolar os recursos de &lt;strong&gt;cada&lt;/strong&gt; Namespace, para que esses recursos sejam bem distribuídos para cada um, de acordo com suas necessidades e, não só isso, para que os seus recursos não afetem o funcionamento de outros processos fora desse Namespace.&lt;/p&gt;

&lt;h3&gt;
  
  
  File System → Overlay File System (OFS)
&lt;/h3&gt;

&lt;p&gt;Novamente, vamos contextualizar o funcionamento do &lt;strong&gt;Overlay File System&lt;/strong&gt; para uma melhor compreensão: Digamos que temos um container em que estamos rodando uma aplicação de, aproximadamente, 95mb (Megabytes), porém, para que essa aplicação funcione corretamente, é necessário a utilização de duas dependências diferentes. &lt;br&gt;
A partir disso, podemos citar o seguinte possível acontecimento: surgiu a necessidade de mudar essa aplicação e, para isso, teremos que criar outra imagem a partir da que temos atualmente (falaremos sobre imagens no próximo tópico). Então, o Overlay File System (OFS) será usado para criar imagens desse novo aplicativo executável. Isso é possível porque ele pode gerar uma nova imagem a partir de uma existente, apenas alterando as partes que precisam ser atualizadas, sem a necessidade de reinstalar as dependências obrigatórias.&lt;/p&gt;

&lt;p&gt;Agora que conhecemos um pouco sobre o funcionamento dos containers e de seus 3 pilares, podemos adentrar um pouco mais em outro tópicos importantes quando o assunto é Docker, bem como o conceito de &lt;em&gt;Imagens&lt;/em&gt; &amp;amp; o tão importante &lt;em&gt;DockerFile&lt;/em&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  Imagens
&lt;/h3&gt;

&lt;p&gt;De forma bem objetiva, podemos definir as imagens como um “pacote” executável (ou um conjunto de dependências encadeadas) que possui todos os requisitos/dependências necessários(as) para rodar um aplicativo, incluindo, um arquivo de configuração, variáveis de ambiente, bibliotecas e assim por diante.&lt;/p&gt;


&lt;h3&gt;
  
  
  DockerFile
&lt;/h3&gt;

&lt;p&gt;Para a &lt;strong&gt;criação&lt;/strong&gt; de imagens, utilizamos o &lt;strong&gt;DockerFile&lt;/strong&gt;. Basicamente, ele é um arquivo &lt;em&gt;declarativo&lt;/em&gt; que cita instruções ao container Docker de como será criada e “buildada” a referente imagem que queremos criar.&lt;br&gt;
De maneira usual, (quase) sempre criamos uma imagem a partir de outra imagem já existente, com suas devidas dependências pré-definidas e configuradas e vamos moldando-a de acordo com nossa necessidade.&lt;/p&gt;

&lt;p&gt;Abaixo segue um exemplo de modelo de uma implementação do DockerFile, Vamos explicar linha a linha o que cada uma faz e sua respectiva função:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:16.18.0-alpine as base
RUN npm install

EXPOSE 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Essa primeira linha (logo abaixo) é de extrema importância, pois referencia ao DockerFile a imagem base utilizaremos para a criação da nossa.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:16.18.0-alpine as base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Aqui, dizemos ao DockerFile que será necessário que ele rode esse comando determinado, lembrando: você pode determinar que sejam executados mais de um comando, dessa forma:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN npm install
RUN npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;E, por último (não é o último comando que podemos determinar ao DockerFile e, sim o último de minha demonstração), podemos expôr portas em que essas imagens estarão rodando para que possamos acessá-las quando quisermos:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPOSE 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acredito que agora você já possui conhecimento suficiente para aprofundar-se nos estudos em Docker e, caso precise de alguma ajuda com algum conteito ou recomendação de cursos sobre o assunto, me manda solicitação no &lt;a href="https://www.linkedin.com/in/joelbrs" rel="noopener noreferrer"&gt;meu LinkedIn&lt;/a&gt;, que ficarei feliz em ajudá-lo. Além disso, espero que esse post tenha sido de muita ajuda e estarei sempre disposto a receber feedbacks!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>beginners</category>
      <category>docker</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
